Commit f3a75379 authored by Thomas BOUTROUE's avatar Thomas BOUTROUE

Add new PhysicalGroup object

Add better handling of table delegate for physical items

Enhance look and behavior of physical items delegates
parent 31682a1f
......@@ -24,13 +24,18 @@ AnalogActuator::AnalogActuator (QObject * parent)
, m_minSpeed (0)
, m_maxSpeed (1)
, m_valSpeed (0)
, m_percents (0)
, m_decimals (0)
, m_useSplitPoint (false)
, m_sourceLink (Q_NULLPTR)
, m_targetLink (Q_NULLPTR)
{
connect (this, &AnalogActuator::valRawChanged, this, &AnalogActuator::refreshValSpeed);
connect (this, &AnalogActuator::minRawChanged, this, &AnalogActuator::refreshValSpeed);
connect (this, &AnalogActuator::maxRawChanged, this, &AnalogActuator::refreshValSpeed);
connect (this, &AnalogActuator::valRawChanged, this, &AnalogActuator::refreshPercents);
connect (this, &AnalogActuator::minRawChanged, this, &AnalogActuator::refreshPercents);
connect (this, &AnalogActuator::maxRawChanged, this, &AnalogActuator::refreshPercents);
Manager::instance ().registerObject (this);
}
......@@ -53,6 +58,24 @@ void AnalogActuator::refreshValSpeed (void) {
update_valSpeed (MathUtils::convert (m_valRaw, m_minRaw, m_maxRaw, m_minSpeed, m_maxSpeed));
}
void AnalogActuator::refreshPercents (void) {
if (m_useSplitPoint) {
const int midRaw = (m_maxRaw + m_minRaw) / 2;
if (m_valRaw > midRaw) { // positive value
update_percents (MathUtils::convert (m_valRaw, midRaw, m_maxRaw, 0, +100));
}
else if (m_valRaw < midRaw) { // negative value
update_percents (MathUtils::convert (m_valRaw, midRaw, m_minRaw, 0, -100));
}
else {
update_percents (0);
}
}
else {
update_percents (MathUtils::convert (m_valRaw, m_minRaw, m_maxRaw, 0, 100));
}
}
QJsonObject AnalogActuator::exportState (void) const {
return QJsonObject {
{ "valRaw", m_valRaw },
......
......@@ -36,8 +36,11 @@ class AnalogActuator : public AbstractActuator {
QML_WRITABLE_VAR_PROPERTY (int, minSpeed)
QML_WRITABLE_VAR_PROPERTY (int, maxSpeed)
QML_READONLY_VAR_PROPERTY (int, valSpeed)
// percent value
QML_READONLY_VAR_PROPERTY (int, percents)
// display options
QML_WRITABLE_VAR_PROPERTY (int, decimals)
QML_WRITABLE_VAR_PROPERTY (bool, useSplitPoint)
QML_WRITABLE_CSTREF_PROPERTY (QString, unit)
// source link
QML_WRITABLE_PTR_PROPERTY (LinkAnalogOutputToAnalogActuator, sourceLink)
......@@ -51,6 +54,7 @@ public:
void onComponentCompleted (void) Q_DECL_FINAL;
void refreshValSpeed (void);
void refreshPercents (void);
QJsonObject exportState (void) const Q_DECL_FINAL;
};
......
......@@ -157,6 +157,9 @@ Project {
"components/DelegateLinkTarget.qml",
"components/DelegateMethodHelp.qml",
"components/DelegateObjectHelp.qml",
"components/DelegatePhyBlockTable.qml",
"components/DelegatePhyGroupTable.qml",
"components/DelegatePhyMarkerTable.qml",
"components/DelegatePhyValTable.qml",
"components/DelegatePropertyHelp.qml",
"components/DelegateRoutineOnCanFrame.qml",
......@@ -180,6 +183,7 @@ Project {
"components/DialogImportSnapshot.qml",
"components/DialogOpenNetworkDefinition.qml",
"components/DialogPrintDatasheet.qml",
"components/ExpandableGroup.qml",
"components/InstanceCreator.qml",
"components/SymbolPlug.qml",
"components/WindowCodeEditor.qml",
......
......@@ -37,7 +37,7 @@ QML_ENUM_CLASS (ObjectFamily,
ANGLE,
BLOCK,
MARKER,
STATE,
GROUP,
WORLD,
CANOPEN,
CANBUS,
......
......@@ -108,6 +108,7 @@ Manager::Manager (void)
, m_physicalValues (500)
, m_physicalBlocks (10)
, m_physicalMarkers (20)
, m_physicalGroups (5)
, m_canOpens (20)
, m_canBuses (5)
, m_serialBuses (5)
......@@ -308,6 +309,7 @@ void Manager::deinit (void) {
m_physicalValues.clear ();
m_physicalBlocks.clear ();
m_physicalMarkers.clear ();
m_physicalGroups.clear ();
m_routines.clear ();
m_routinesOnTimer.clear ();
m_routinesOnEvent.clear ();
......@@ -957,6 +959,11 @@ void Manager::doInitObjects (void) {
marker->refreshAncestors ();
usePath = true;
}
else if (PhysicalGroup * group = basicObject->as<PhysicalGroup> ()) {
dump ("GROUP", group);
m_physicalGroups.add (group);
usePath = true;
}
else if (PhysicalWorld * world = basicObject->as<PhysicalWorld> ()) {
dump ("WORLD", world);
m_physicalWorld = world;
......
......@@ -74,6 +74,7 @@ class LinkDigitalOutputToHybridActuator;
class LinkHybridActuatorToPhysicalValue;
class PhysicalWorld;
class PhysicalGroup;
class PhysicalValue;
class PhysicalBlock;
class PhysicalMarker;
......@@ -250,6 +251,7 @@ protected:
Collection<PhysicalValue> m_physicalValues;
Collection<PhysicalBlock> m_physicalBlocks;
Collection<PhysicalMarker> m_physicalMarkers;
Collection<PhysicalGroup> m_physicalGroups;
Collection<CanOpen> m_canOpens;
Collection<CanBus> m_canBuses;
......
......@@ -466,15 +466,28 @@ QJsonObject PhysicalBlock::exportState (void) const {
};
}
PhysicalGroup::PhysicalGroup (QObject * parent)
: BasicObject (ObjectFamily::GROUP, parent)
, m_subObjects (this)
{
Manager::instance ().registerObject (this);
}
PhysicalGroup::~PhysicalGroup (void) {
Manager::instance ().unregisterObject (this);
}
void PhysicalGroup::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
Manager::instance ().intializeObject (this);
}
PhysicalWorld::PhysicalWorld (QObject * parent)
: BasicObject (ObjectFamily::WORLD, parent)
, m_subObjects (this)
, m_dirty (false)
{
m_bounds = new PhysicalSize (this);
m_blocks = new BasicObjectsModel (this);
m_values = new BasicObjectsModel (this);
m_markers = new BasicObjectsModel (this);
m_bounds->set_uid ("BOUNDS");
m_bounds->onComponentCompleted ();
Manager::instance ().registerObject (this);
......@@ -486,9 +499,6 @@ PhysicalWorld::~PhysicalWorld (void) {
void PhysicalWorld::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
m_blocks->appendIf<PhysicalBlock> (m_subObjects.items ());
m_values->appendIf<PhysicalValue> (m_subObjects.items ());
m_markers->appendIf<PhysicalMarker> (m_subObjects.items ());
Manager::instance ().intializeObject (this);
}
......
......@@ -230,14 +230,22 @@ public:
void refreshAncestors (void);
};
class PhysicalGroup : public BasicObject {
Q_OBJECT
QML_DEFAULT_PROPERTY (subObjects)
QML_LIST_PROPERTY (QObject, subObjects)
public:
explicit PhysicalGroup (QObject * parent = Q_NULLPTR);
virtual ~PhysicalGroup (void);
void onComponentCompleted (void) Q_DECL_FINAL;
};
class PhysicalWorld : public BasicObject {
Q_OBJECT
Q_INTERFACES (QQmlParserStatus)
QML_DEFAULT_PROPERTY (subObjects)
QML_LIST_PROPERTY (QObject, subObjects)
QML_CONSTANT_PTR_PROPERTY (BasicObjectsModel, blocks)
QML_CONSTANT_PTR_PROPERTY (BasicObjectsModel, values)
QML_CONSTANT_PTR_PROPERTY (BasicObjectsModel, markers)
QML_CONSTANT_PTR_PROPERTY (PhysicalSize, bounds) // boundaries on 6 sides
public:
......
......@@ -186,6 +186,7 @@ void SharedObject::registerQmlTypes (QQmlEngine * qmlEngine) {
qmlRegisterType<PhysicalBlock> (uri, maj, min, "PhysicalBlock");
qmlRegisterType<PhysicalValue> (uri, maj, min, "PhysicalValue");
qmlRegisterType<PhysicalMarker> (uri, maj, min, "PhysicalMarker");
qmlRegisterType<PhysicalGroup> (uri, maj, min, "PhysicalGroup");
qmlRegisterType<PhysicalWorld> (uri, maj, min, "PhysicalWorld");
qmlRegisterType<RoutineOnCanFrame> (uri, maj, min, "RoutineOnCanFrame");
qmlRegisterType<RoutineOnSerialFrame> (uri, maj, min, "RoutineOnSerialFrame");
......
......@@ -15,6 +15,7 @@ StretchColumnContainer {
SliderBar {
id: slider;
useSplit: (actuator ? actuator.useSplitPoint : false);
minValue: (actuator ? actuator.minRaw : 0);
maxValue: (actuator ? actuator.maxRaw : 1);
enabled: (actuator
......@@ -87,7 +88,7 @@ StretchColumnContainer {
}
Stretcher { }
TextLabel {
text: (actuator ? (100 * (actuator.valRaw - actuator.minRaw) / (actuator.maxRaw - actuator.minRaw)).toFixed () : "");
text: (actuator ? actuator.percents : "");
font.family: Style.fontFixedName;
anchors.baseline: lblActuatorPercent.baseline;
}
......@@ -97,10 +98,11 @@ StretchColumnContainer {
anchors.baseline: lblActuatorPercent.baseline;
}
TextLabel {
text: "(" + [
"0",
"100",
].join (Style.charThreeDots) + ")";
text: (actuator
? (actuator.useSplitPoint
? ("(-100" + Style.charThreeDots + "100)")
: ("(0" + Style.charThreeDots + "100)"))
: "");
color: Style.colorBorder;
font.family: Style.fontFixedName;
font.pixelSize: Style.fontSizeSmall;
......
......@@ -4,6 +4,7 @@ import QtCAN.CanTestBench 2.0;
SliderBar {
barSize: Style.spacingNormal;
useSplit: (actuator ? actuator.useSplitPoint : false);
handleSize: (barSize * 1.5);
minValue: (actuator ? actuator.minRaw : 0);
maxValue: (actuator ? actuator.maxRaw : 1);
......
import QtQuick 2.1;
import QtQmlTricks.UiElements 2.0;
import QtQmlTricks.SmartDataModels 2.0;
import QtCAN.CanTestBench 2.0;
ExpandableGroup {
id: base;
iconItem: Rectangle {
color: block.color;
implicitWidth: Style.spacingBig;
implicitHeight: Style.spacingBig;
}
uidLabel {
text: block.uid;
font.pixelSize: Style.fontSizeBig;
}
titleLabel {
text: block.title;
font.pixelSize: Style.fontSizeBig;
}
ExtraAnchors.horizontalFill: parent;
property PhysicalBlock block : null;
signal needVisible (Item item);
Repeater {
model: [
block.pivotPos,
block.size,
block.angle,
block.absoluteAngle,
];
delegate: ExpandableGroup {
id: delegateDimensionTable;
visible: (phyValEditableCount || !toggleShowOnlyEditable.checked);
uidLabel {
text: delegateDimensionTable.dimension.uid;
font.italic: true;
}
ExtraAnchors.horizontalFill: parent;
readonly property BasicObject dimension : modelData;
readonly property var phyValList : {
var ret = [];
switch (dimension.family) {
case ObjectFamily.POSITION:
ret.push (dimension ["onLeftToRight"]);
ret.push (dimension ["onBackToFront"]);
ret.push (dimension ["onBottomToTop"]);
break;
case ObjectFamily.SIZE:
ret.push (dimension ["toLeft"]);
ret.push (dimension ["toRight"]);
ret.push (dimension ["toBack"]);
ret.push (dimension ["toFront"]);
ret.push (dimension ["toBottom"]);
ret.push (dimension ["toTop"]);
break;
case ObjectFamily.ANGLE:
ret.push (dimension ["yaw"]);
ret.push (dimension ["pitch"]);
ret.push (dimension ["roll"]);
break;
}
return ret;
}
readonly property int phyValEditableCount : {
var ret = 0;
phyValList.forEach (function (phyVal) {
if (phyVal.min !== phyVal.max) {
++ret;
}
});
return ret;
}
Repeater {
id: repeaterDimensionsPhyVal;
model: delegateDimensionTable.phyValList;
delegate: DelegatePhyValTable {
id: delegatePhyValTable
phyVal: modelData;
visible: (editable || !toggleShowOnlyEditable.checked);
ExtraAnchors.horizontalFill: parent;
onNeedVisible: {
delegateDimensionTable.expanded = true;
base.expanded = true;
base.needVisible (item);
}
onValueEdited: {
if (delegateDimensionTable.dimension === block.absoluteAngle) {
var oldAbs = phyVal.val;
var newAbs = value;
var delta = (newAbs - oldAbs);
var relVal = null;
if (phyVal === block.absoluteAngle.yaw) {
relVal = block.angle.yaw;
}
else if (phyVal === block.absoluteAngle.pitch) {
relVal = block.angle.pitch;
}
else if (phyVal === block.absoluteAngle.roll) {
relVal = block.angle.roll;
}
else { }
if (relVal) {
var tmp = (relVal.val + delta);
relVal.val = (tmp > relVal.max ? relVal.max : (tmp < relVal.min ? relVal.min : tmp));
}
}
else {
phyVal.val = value;
}
}
}
}
}
}
}
import QtQuick 2.1;
import QtQmlTricks.UiElements 2.0;
import QtQmlTricks.SmartDataModels 2.0;
import QtCAN.CanTestBench 2.0;
ExpandableGroup {
id: base;
uidLabel {
text: group.uid;
emphasis: true;
font.pixelSize: Style.fontSizeBig;
}
titleLabel {
text: group.title;
font.pixelSize: Style.fontSizeBig;
}
ExtraAnchors.horizontalFill: parent;
property PhysicalGroup group : null;
signal needVisible (Item item);
Repeater {
model: group.subObjects;
delegate: InstanceCreator {
id: creator;
component: {
switch (modelData ["family"]) {
case ObjectFamily.VALUE: return compoDelegatePhyVal;
case ObjectFamily.GROUP: return compoDelegatePhyGroup;
case ObjectFamily.BLOCK: return compoDelegatePhyBlock;
case ObjectFamily.MARKER: return compoDelegatePhyMarker;
default: return null;
}
}
properties: {
switch (modelData ["family"]) {
case ObjectFamily.VALUE: return ({ "phyVal" : modelData });
case ObjectFamily.GROUP: return ({ "group" : modelData });
case ObjectFamily.BLOCK: return ({ "block" : modelData });
case ObjectFamily.MARKER: return ({ "marker" : modelData });
default: return ({});
}
}
ExtraAnchors.horizontalFill: parent;
Connections {
target: creator.instance;
ignoreUnknownSignals: true;
onNeedVisible: {
base.expanded = true;
base.needVisible (item);
}
}
}
}
}
import QtQuick 2.1;
import QtQmlTricks.UiElements 2.0;
import QtQmlTricks.SmartDataModels 2.0;
import QtCAN.CanTestBench 2.0;
MouseArea {
id: base;
height: implicitHeight;
hoverEnabled: true;
ExtraAnchors.horizontalFill: parent;
property PhysicalMarker marker : null;
signal needVisible (Item item);
// TODO : add visual components
}
......@@ -7,7 +7,8 @@ MouseArea {
id: delegatePhyValTable;
height: implicitHeight;
hoverEnabled: true;
implicitHeight: layoutValPhyTable.height;
implicitHeight: (layoutValPhyTable.height + layoutValPhyTable.anchors.margins * 2);
ExtraAnchors.horizontalFill: parent;
onCurrentChanged: {
if (current) {
timerEnsureVisible.restart ();
......@@ -20,23 +21,33 @@ MouseArea {
}
}
property PhysicalValue phyVal : null;
property ScrollContainer scroller : null;
property PhysicalValue phyVal : null;
readonly property bool current : (phyVal === highlightPhyVal);
readonly property bool editable : (phyVal.min !== phyVal.max);
signal needVisible (Item item);
signal valueEdited (real value);
Rectangle {
color: Style.colorSecondary;
opacity: 0.15;
border {
width: Style.lineSize;
color: Style.colorBorder;
}
anchors.fill: parent;
}
Rectangle {
color: Style.opacify (Style.colorHighlight, 0.35);
visible: delegatePhyValTable.containsMouse;
anchors.fill: parent;
anchors.margins: -Style.spacingSmall;
}
StretchRowContainer {
id: layoutValPhyTable;
spacing: Style.spacingNormal;
anchors.margins: Style.spacingSmall;
anchors.verticalCenter: parent.verticalCenter;
ExtraAnchors.horizontalFill: parent;
Timer {
......@@ -44,7 +55,7 @@ MouseArea {
repeat: false;
running: false;
interval: 10;
onTriggered: { scroller.ensureVisible (delegatePhyValTable); }
onTriggered: { needVisible (base); }
}
TextLabel {
text: delegatePhyValTable.phyVal.uid;
......
import QtQuick 2.1;
import QtQmlTricks.UiElements 2.0;
import QtQmlTricks.SmartDataModels 2.0;
import QtCAN.CanTestBench 2.0;
Item {
id: base;
implicitHeight: (layoutMain.height + layoutMain.anchors.margins * 2);
property alias iconItem : icoLoader.component;
property alias expanded : layoutItems.visible;
readonly property alias uidLabel : lblUid;
readonly property alias titleLabel : lblTitle;
default property alias content : layoutItems.data;
Rectangle {
color: Style.colorSecondary;
opacity: 0.15;
border {
width: Style.lineSize;
color: Style.colorBorder;
}
anchors.fill: parent;
}
Column {
id: layoutMain;
spacing: Style.spacingNormal;
anchors {
margins: Style.spacingSmall;
verticalCenter: parent.verticalCenter;
}
ExtraAnchors.horizontalFill: parent;
MouseArea {
implicitHeight: layoutHeader.height;
ExtraAnchors.horizontalFill: parent;
onClicked: { expanded = !expanded; }
StretchRowContainer {
id: layoutHeader;
spacing: Style.spacingNormal;
ExtraAnchors.horizontalFill: parent;
InstanceCreator {
id: icoLoader;
anchors.verticalCenter: parent.verticalCenter;
}
TextLabel {
id: lblUid;
anchors.verticalCenter: parent.verticalCenter;
}
TextLabel {
id: lblTitle;
anchors.verticalCenter: parent.verticalCenter;
}
Stretcher { }
SvgIconLoader {
icon: (layoutItems.visible
? "actions/chevron-down"
: "actions/chevron-right");
color: Style.colorForeground;
anchors.verticalCenter: parent.verticalCenter;
}
}
}
Column {
id: layoutItems;
spacing: Style.spacingSmall;
anchors.margins: Style.spacingBig;
ExtraAnchors.horizontalFill: parent;
// CONTENT HERE
}
}
}
......@@ -2,8 +2,8 @@ import QtQuick 2.1;
Item {
id: base;
implicitWidth: (priv.instance ? priv.instance.implicitWidth : 0);
implicitHeight: (priv.instance ? priv.instance.implicitHeight : 0);
implicitWidth: (instance ? priv.instance.implicitWidth : 0);
implicitHeight: (instance ? priv.instance.implicitHeight : 0);
onComponentChanged: { priv.restart (); }
onPropertiesChanged: { priv.restart (); }
Component.onCompleted: { priv.restart (); }
......@@ -11,6 +11,8 @@ Item {
property Component component : null;
property var properties : ({});
readonly property Item instance : priv.instance;
Timer {
id: priv;
repeat: false;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment