pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/gui/ConfigWidget.cc

3426 lines
105 KiB
C++

/*
* Copyright (C) 2014 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include "gazebo/common/Console.hh"
#include "gazebo/gui/ConfigWidget.hh"
#include "gazebo/gui/ConfigWidgetPrivate.hh"
using namespace gazebo;
using namespace gui;
const std::vector<QString> ConfigWidget::bgColors(
{"#999999", "#777777", "#555555", "#333333"});
const std::vector<QString> ConfigWidget::widgetColors(
{"#eeeeee", "#cccccc", "#aaaaaa", "#888888"});
const QString ConfigWidget::redColor = "#d42b2b";
const QString ConfigWidget::greenColor = "#3bc43b";
const QString ConfigWidget::blueColor = "#0d0df2";
/////////////////////////////////////////////////
ConfigWidget::ConfigWidget()
: dataPtr(new ConfigWidgetPrivate())
{
this->dataPtr->configMsg = nullptr;
this->setObjectName("configWidget");
}
/////////////////////////////////////////////////
ConfigWidget::~ConfigWidget()
{
delete this->dataPtr->configMsg;
}
/////////////////////////////////////////////////
void ConfigWidget::Load(const google::protobuf::Message *_msg)
{
this->dataPtr->configMsg = _msg->New();
this->dataPtr->configMsg->CopyFrom(*_msg);
QWidget *widget = this->Parse(this->dataPtr->configMsg, 0);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setAlignment(Qt::AlignTop);
mainLayout->addWidget(widget);
this->setLayout(mainLayout);
// set up event filter for scrollable widgets to make sure they don't steal
// focus when embedded in a QScrollArea.
QList<QAbstractSpinBox *> spinBoxes =
this->findChildren<QAbstractSpinBox *>();
for (int i = 0; i < spinBoxes.size(); ++i)
{
spinBoxes[i]->installEventFilter(this);
spinBoxes[i]->setFocusPolicy(Qt::StrongFocus);
}
QList<QComboBox *> comboBoxes =
this->findChildren<QComboBox *>();
for (int i = 0; i < comboBoxes.size(); ++i)
{
comboBoxes[i]->installEventFilter(this);
comboBoxes[i]->setFocusPolicy(Qt::StrongFocus);
}
}
/////////////////////////////////////////////////
void ConfigWidget::UpdateFromMsg(const google::protobuf::Message *_msg)
{
this->dataPtr->configMsg->CopyFrom(*_msg);
this->Parse(this->dataPtr->configMsg, true);
}
/////////////////////////////////////////////////
google::protobuf::Message *ConfigWidget::GetMsg()
{
return this->Msg();
}
/////////////////////////////////////////////////
google::protobuf::Message *ConfigWidget::Msg()
{
this->UpdateMsg(this->dataPtr->configMsg);
return this->dataPtr->configMsg;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GetHumanReadableKey(const std::string &_key)
{
return this->HumanReadableKey(_key);
}
/////////////////////////////////////////////////
std::string ConfigWidget::HumanReadableKey(const std::string &_key) const
{
std::string humanKey = _key;
humanKey[0] = std::toupper(humanKey[0]);
std::replace(humanKey.begin(), humanKey.end(), '_', ' ');
return humanKey;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GetUnitFromKey(const std::string &_key,
const std::string &_jointType)
{
return this->UnitFromKey(_key, _jointType);
}
/////////////////////////////////////////////////
std::string ConfigWidget::UnitFromKey(const std::string &_key,
const std::string &_jointType) const
{
if (_key == "pos" || _key == "length" || _key == "min_depth")
{
return "m";
}
if (_key == "rot")
return "rad";
if (_key == "kp" || _key == "kd")
return "N/m";
if (_key == "max_vel")
return "m/s";
if (_key == "mass")
return "kg";
if (_key == "ixx" || _key == "ixy" || _key == "ixz" ||
_key == "iyy" || _key == "iyz" || _key == "izz")
{
return "kg&middot;m<sup>2</sup>";
}
if (_key == "limit_lower" || _key == "limit_upper")
{
if (_jointType == "PRISMATIC")
return "m";
else if (_jointType != "")
return "rad";
}
if (_key == "limit_effort")
{
if (_jointType == "PRISMATIC")
return "N";
else if (_jointType != "")
return "Nm";
}
if (_key == "limit_velocity" || _key == "velocity")
{
if (_jointType == "PRISMATIC")
return "m/s";
else if (_jointType != "")
return "rad/s";
}
if (_key == "damping")
{
if (_jointType == "PRISMATIC")
return "Ns/m";
else if (_jointType != "")
return "Ns";
}
if (_key == "friction")
{
if (_jointType == "PRISMATIC")
return "N";
else if (_jointType != "")
return "Nm";
}
return "";
}
/////////////////////////////////////////////////
void ConfigWidget::GetRangeFromKey(const std::string &_key, double &_min,
double &_max)
{
this->RangeFromKey(_key, _min, _max);
}
/////////////////////////////////////////////////
void ConfigWidget::RangeFromKey(const std::string &_key, double &_min,
double &_max) const
{
// Maximum range by default
_min = -GZ_DBL_MAX;
_max = GZ_DBL_MAX;
if (_key == "mass" || _key == "ixx" || _key == "ixy" || _key == "ixz" ||
_key == "iyy" || _key == "iyz" || _key == "izz" || _key == "length" ||
_key == "min_depth")
{
_min = 0;
}
else if (_key == "bounce" || _key == "transparency" ||
_key == "laser_retro" || _key == "ambient" || _key == "diffuse" ||
_key == "specular" || _key == "emissive" ||
_key == "restitution_coefficient")
{
_min = 0;
_max = 1;
}
else if (_key == "fdir1" || _key == "xyz")
{
_min = -1;
_max = +1;
}
}
/////////////////////////////////////////////////
bool ConfigWidget::GetWidgetVisible(const std::string &_name) const
{
return this->WidgetVisible(_name);
}
/////////////////////////////////////////////////
bool ConfigWidget::WidgetVisible(const std::string &_name) const
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
{
if (iter->second->groupWidget)
{
GroupWidget *groupWidget =
qobject_cast<GroupWidget *>(iter->second->groupWidget);
if (groupWidget)
{
return groupWidget->isVisible();
}
}
return iter->second->isVisible();
}
return false;
}
/////////////////////////////////////////////////
void ConfigWidget::SetWidgetVisible(const std::string &_name, bool _visible)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
{
if (iter->second->groupWidget)
{
GroupWidget *groupWidget =
qobject_cast<GroupWidget *>(iter->second->groupWidget);
if (groupWidget)
{
groupWidget->setVisible(_visible);
return;
}
}
iter->second->setVisible(_visible);
}
}
/////////////////////////////////////////////////
bool ConfigWidget::GetWidgetReadOnly(const std::string &_name) const
{
return this->WidgetReadOnly(_name);
}
/////////////////////////////////////////////////
bool ConfigWidget::WidgetReadOnly(const std::string &_name) const
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
{
if (iter->second->groupWidget)
{
GroupWidget *groupWidget =
qobject_cast<GroupWidget *>(iter->second->groupWidget);
if (groupWidget)
{
return !groupWidget->isEnabled();
}
}
return !iter->second->isEnabled();
}
return false;
}
/////////////////////////////////////////////////
void ConfigWidget::SetWidgetReadOnly(const std::string &_name, bool _readOnly)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
{
if (iter->second->groupWidget)
{
GroupWidget *groupWidget =
qobject_cast<GroupWidget *>(iter->second->groupWidget);
if (groupWidget)
{
groupWidget->setEnabled(!_readOnly);
// Qt docs: "Disabling a widget implicitly disables all its children.
// Enabling respectively enables all child widgets unless they have
// been explicitly disabled."
auto childWidgets = groupWidget->findChildren<QWidget *>();
for (auto widget : childWidgets)
widget->setEnabled(!_readOnly);
return;
}
}
iter->second->setEnabled(!_readOnly);
}
}
/////////////////////////////////////////////////
bool ConfigWidget::SetIntWidgetValue(const std::string &_name, int _value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateIntWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetUIntWidgetValue(const std::string &_name,
unsigned int _value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateUIntWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetDoubleWidgetValue(const std::string &_name,
double _value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateDoubleWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetBoolWidgetValue(const std::string &_name,
bool _value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateBoolWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetStringWidgetValue(const std::string &_name,
const std::string &_value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateStringWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetVector3WidgetValue(const std::string &_name,
const math::Vector3 &_value)
{
return this->SetVector3dWidgetValue(_name, _value.Ign());
}
/////////////////////////////////////////////////
bool ConfigWidget::SetVector3dWidgetValue(const std::string &_name,
const ignition::math::Vector3d &_value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateVector3dWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetColorWidgetValue(const std::string &_name,
const common::Color &_value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateColorWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetPoseWidgetValue(const std::string &_name,
const math::Pose &_value)
{
return this->SetPoseWidgetValue(_name, _value.Ign());
}
/////////////////////////////////////////////////
bool ConfigWidget::SetPoseWidgetValue(const std::string &_name,
const ignition::math::Pose3d &_value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdatePoseWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetGeometryWidgetValue(const std::string &_name,
const std::string &_value, const math::Vector3 &_dimensions,
const std::string &_uri)
{
return this->SetGeometryWidgetValue(_name, _value, _dimensions.Ign(), _uri);
}
/////////////////////////////////////////////////
bool ConfigWidget::SetGeometryWidgetValue(const std::string &_name,
const std::string &_value, const ignition::math::Vector3d &_dimensions,
const std::string &_uri)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateGeometryWidget(iter->second, _value, _dimensions, _uri);
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::SetEnumWidgetValue(const std::string &_name,
const std::string &_value)
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return this->UpdateEnumWidget(iter->second, _value);
return false;
}
/////////////////////////////////////////////////
int ConfigWidget::GetIntWidgetValue(const std::string &_name) const
{
return this->IntWidgetValue(_name);
}
/////////////////////////////////////////////////
int ConfigWidget::IntWidgetValue(const std::string &_name) const
{
int value = 0;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->IntWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
unsigned int ConfigWidget::GetUIntWidgetValue(const std::string &_name) const
{
return this->UIntWidgetValue(_name);
}
/////////////////////////////////////////////////
unsigned int ConfigWidget::UIntWidgetValue(const std::string &_name) const
{
unsigned int value = 0;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->UIntWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
double ConfigWidget::GetDoubleWidgetValue(const std::string &_name) const
{
return this->DoubleWidgetValue(_name);
}
/////////////////////////////////////////////////
double ConfigWidget::DoubleWidgetValue(const std::string &_name) const
{
double value = 0.0;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->DoubleWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
bool ConfigWidget::GetBoolWidgetValue(const std::string &_name) const
{
return this->BoolWidgetValue(_name);
}
/////////////////////////////////////////////////
bool ConfigWidget::BoolWidgetValue(const std::string &_name) const
{
bool value = false;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->BoolWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GetStringWidgetValue(const std::string &_name) const
{
return this->StringWidgetValue(_name);
}
/////////////////////////////////////////////////
std::string ConfigWidget::StringWidgetValue(const std::string &_name) const
{
std::string value;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->StringWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
math::Vector3 ConfigWidget::GetVector3WidgetValue(const std::string &_name)
const
{
return this->Vector3dWidgetValue(_name);
}
/////////////////////////////////////////////////
ignition::math::Vector3d ConfigWidget::Vector3dWidgetValue(
const std::string &_name) const
{
ignition::math::Vector3d value;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->Vector3dWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
common::Color ConfigWidget::GetColorWidgetValue(const std::string &_name) const
{
return this->ColorWidgetValue(_name);
}
/////////////////////////////////////////////////
common::Color ConfigWidget::ColorWidgetValue(const std::string &_name) const
{
common::Color value;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->ColorWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
math::Pose ConfigWidget::GetPoseWidgetValue(const std::string &_name) const
{
return this->PoseWidgetValue(_name);
}
/////////////////////////////////////////////////
ignition::math::Pose3d ConfigWidget::PoseWidgetValue(const std::string &_name)
const
{
ignition::math::Pose3d value;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->PoseWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GetGeometryWidgetValue(const std::string &_name,
math::Vector3 &_dimensions, std::string &_uri) const
{
ignition::math::Vector3d dimensions;
std::string type = this->GeometryWidgetValue(_name, dimensions, _uri);
_dimensions = dimensions;
return type;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GeometryWidgetValue(const std::string &_name,
ignition::math::Vector3d &_dimensions, std::string &_uri) const
{
std::string type;
std::map <std::string, ConfigChildWidget *>::const_iterator iter =
this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
type = this->GeometryWidgetValue(iter->second, _dimensions, _uri);
return type;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GetEnumWidgetValue(const std::string &_name) const
{
return this->EnumWidgetValue(_name);
}
/////////////////////////////////////////////////
std::string ConfigWidget::EnumWidgetValue(const std::string &_name) const
{
std::string value;
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
value = this->EnumWidgetValue(iter->second);
return value;
}
/////////////////////////////////////////////////
QWidget *ConfigWidget::Parse(google::protobuf::Message *_msg,
bool _update, const std::string &_name, const int _level)
{
std::vector<QWidget *> newWidgets;
const google::protobuf::Descriptor *d = _msg->GetDescriptor();
if (!d)
return NULL;
unsigned int count = d->field_count();
for (unsigned int i = 0; i < count ; ++i)
{
const google::protobuf::FieldDescriptor *field = d->field(i);
if (!field)
return NULL;
const google::protobuf::Reflection *ref = _msg->GetReflection();
if (!ref)
return NULL;
std::string name = field->name();
// Parse each field in the message
// TODO parse repeated fields
if (!field->is_repeated())
{
if (_update && !ref->HasField(*_msg, field))
continue;
QWidget *newFieldWidget = NULL;
ConfigChildWidget *configChildWidget = NULL;
bool newWidget = true;
std::string scopedName = _name.empty() ? name : _name + "::" + name;
if (this->dataPtr->configWidgets.find(scopedName) !=
this->dataPtr->configWidgets.end())
{
newWidget = false;
configChildWidget = this->dataPtr->configWidgets[scopedName];
}
switch (field->type())
{
case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
{
double value = ref->GetDouble(*_msg, field);
if (!math::equal(value, value))
value = 0;
if (newWidget)
{
configChildWidget = this->CreateDoubleWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateDoubleWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_FLOAT:
{
float value = ref->GetFloat(*_msg, field);
if (!math::equal(value, value))
value = 0;
if (newWidget)
{
configChildWidget = this->CreateDoubleWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateDoubleWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_INT64:
{
int64_t value = ref->GetInt64(*_msg, field);
if (newWidget)
{
configChildWidget = this->CreateIntWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateIntWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_UINT64:
{
uint64_t value = ref->GetUInt64(*_msg, field);
if (newWidget)
{
configChildWidget = this->CreateUIntWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateUIntWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_INT32:
{
int32_t value = ref->GetInt32(*_msg, field);
if (newWidget)
{
configChildWidget = this->CreateIntWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateIntWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_UINT32:
{
uint32_t value = ref->GetUInt32(*_msg, field);
if (newWidget)
{
configChildWidget = this->CreateUIntWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateUIntWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_BOOL:
{
bool value = ref->GetBool(*_msg, field);
if (newWidget)
{
configChildWidget = this->CreateBoolWidget(name, _level);
newFieldWidget = configChildWidget;
}
this->UpdateBoolWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_STRING:
{
std::string value = ref->GetString(*_msg, field);
if (newWidget)
{
// Choose either a one-line or a multi-line widget according to name
std::string type = "line";
if (name == "innerxml")
type = "plain";
configChildWidget = this->CreateStringWidget(name, _level, type);
newFieldWidget = configChildWidget;
}
this->UpdateStringWidget(configChildWidget, value);
break;
}
case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
{
google::protobuf::Message *valueMsg =
ref->MutableMessage(_msg, field);
// parse and create custom geometry widgets
if (field->message_type()->name() == "Geometry")
{
if (newWidget)
{
configChildWidget = this->CreateGeometryWidget(name, _level);
newFieldWidget = configChildWidget;
}
// type
const google::protobuf::Descriptor *valueDescriptor =
valueMsg->GetDescriptor();
const google::protobuf::FieldDescriptor *typeField =
valueDescriptor->FindFieldByName("type");
if (valueMsg->GetReflection()->HasField(*valueMsg, typeField))
{
const google::protobuf::EnumValueDescriptor *typeValueDescriptor =
valueMsg->GetReflection()->GetEnum(*valueMsg, typeField);
std::string geometryTypeStr;
if (typeValueDescriptor)
{
geometryTypeStr =
QString(typeValueDescriptor->name().c_str()).toLower().
toStdString();
}
ignition::math::Vector3d dimensions;
// dimensions
for (int k = 0; k < valueDescriptor->field_count() ; ++k)
{
const google::protobuf::FieldDescriptor *geomField =
valueDescriptor->field(k);
if (geomField->is_repeated())
continue;
if (geomField->type() !=
google::protobuf::FieldDescriptor::TYPE_MESSAGE ||
!valueMsg->GetReflection()->HasField(*valueMsg, geomField))
continue;
google::protobuf::Message *geomValueMsg =
valueMsg->GetReflection()->MutableMessage(
valueMsg, geomField);
const google::protobuf::Descriptor *geomValueDescriptor =
geomValueMsg->GetDescriptor();
std::string geomMsgName = geomField->message_type()->name();
if (geomMsgName == "BoxGeom" || geomMsgName == "MeshGeom")
{
int fieldIdx = (geomMsgName == "BoxGeom") ? 0 : 1;
google::protobuf::Message *geomDimMsg =
geomValueMsg->GetReflection()->MutableMessage(
geomValueMsg, geomValueDescriptor->field(fieldIdx));
dimensions = this->ParseVector3d(geomDimMsg);
break;
}
else if (geomMsgName == "CylinderGeom")
{
const google::protobuf::FieldDescriptor *geomRadiusField =
geomValueDescriptor->FindFieldByName("radius");
double radius = geomValueMsg->GetReflection()->GetDouble(
*geomValueMsg, geomRadiusField);
const google::protobuf::FieldDescriptor *geomLengthField =
geomValueDescriptor->FindFieldByName("length");
double length = geomValueMsg->GetReflection()->GetDouble(
*geomValueMsg, geomLengthField);
dimensions.X(radius * 2.0);
dimensions.Y(dimensions.X());
dimensions.Z(length);
break;
}
else if (geomMsgName == "SphereGeom")
{
const google::protobuf::FieldDescriptor *geomRadiusField =
geomValueDescriptor->FindFieldByName("radius");
double radius = geomValueMsg->GetReflection()->GetDouble(
*geomValueMsg, geomRadiusField);
dimensions.X(radius * 2.0);
dimensions.Y(dimensions.X());
dimensions.Z(dimensions.X());
break;
}
else if (geomMsgName == "PolylineGeom")
{
continue;
}
}
this->UpdateGeometryWidget(configChildWidget,
geometryTypeStr, dimensions);
}
}
// parse and create custom pose widgets
else if (field->message_type()->name() == "Pose")
{
if (newWidget)
{
configChildWidget = this->CreatePoseWidget(name, _level);
newFieldWidget = configChildWidget;
}
ignition::math::Pose3d value;
const google::protobuf::Descriptor *valueDescriptor =
valueMsg->GetDescriptor();
int valueMsgFieldCount = valueDescriptor->field_count();
for (int j = 0; j < valueMsgFieldCount ; ++j)
{
const google::protobuf::FieldDescriptor *valueField =
valueDescriptor->field(j);
if (valueField->type() !=
google::protobuf::FieldDescriptor::TYPE_MESSAGE)
continue;
if (valueField->message_type()->name() == "Vector3d")
{
// pos
google::protobuf::Message *posValueMsg =
valueMsg->GetReflection()->MutableMessage(
valueMsg, valueField);
auto vec3 = this->ParseVector3d(posValueMsg);
value.Pos() = vec3;
}
else if (valueField->message_type()->name() == "Quaternion")
{
// rot
google::protobuf::Message *quatValueMsg =
valueMsg->GetReflection()->MutableMessage(
valueMsg, valueField);
const google::protobuf::Descriptor *quatValueDescriptor =
quatValueMsg->GetDescriptor();
std::vector<double> quatValues;
for (unsigned int k = 0; k < 4; ++k)
{
const google::protobuf::FieldDescriptor *quatValueField =
quatValueDescriptor->field(k);
quatValues.push_back(quatValueMsg->GetReflection()->GetDouble(
*quatValueMsg, quatValueField));
}
ignition::math::Quaterniond quat(quatValues[3], quatValues[0],
quatValues[1], quatValues[2]);
value.Rot() = quat;
}
}
this->UpdatePoseWidget(configChildWidget, value);
}
// parse and create custom vector3 widgets
else if (field->message_type()->name() == "Vector3d")
{
if (newWidget)
{
configChildWidget = this->CreateVector3dWidget(name, _level);
newFieldWidget = configChildWidget;
}
ignition::math::Vector3d vec3 = this->ParseVector3d(valueMsg);
this->UpdateVector3dWidget(configChildWidget, vec3);
}
// parse and create custom color widgets
else if (field->message_type()->name() == "Color")
{
if (newWidget)
{
configChildWidget = this->CreateColorWidget(name, _level);
newFieldWidget = configChildWidget;
}
common::Color color;
const google::protobuf::Descriptor *valueDescriptor =
valueMsg->GetDescriptor();
std::vector<double> values;
for (unsigned int j = 0; j < configChildWidget->widgets.size(); ++j)
{
const google::protobuf::FieldDescriptor *valueField =
valueDescriptor->field(j);
if (valueMsg->GetReflection()->HasField(*valueMsg, valueField))
{
values.push_back(valueMsg->GetReflection()->GetFloat(
*valueMsg, valueField));
}
else
values.push_back(0);
}
color.r = values[0];
color.g = values[1];
color.b = values[2];
color.a = values[3];
this->UpdateColorWidget(configChildWidget, color);
}
else
{
// parse the message fields recursively
QWidget *groupBoxWidget =
this->Parse(valueMsg, _update, scopedName, _level+1);
if (groupBoxWidget)
{
newFieldWidget = new ConfigChildWidget();
QVBoxLayout *groupBoxLayout = new QVBoxLayout;
groupBoxLayout->setContentsMargins(0, 0, 0, 0);
groupBoxLayout->addWidget(groupBoxWidget);
newFieldWidget->setLayout(groupBoxLayout);
qobject_cast<ConfigChildWidget *>(newFieldWidget)->
widgets.push_back(groupBoxWidget);
}
}
if (newWidget)
{
// Make it into a group widget
ConfigChildWidget *childWidget =
qobject_cast<ConfigChildWidget *>(newFieldWidget);
if (childWidget)
{
newFieldWidget = this->CreateGroupWidget(name, childWidget,
_level);
}
}
break;
}
case google::protobuf::FieldDescriptor::TYPE_ENUM:
{
const google::protobuf::EnumValueDescriptor *value =
ref->GetEnum(*_msg, field);
if (!value)
{
gzerr << "Error retrieving enum value for '" << name << "'"
<< std::endl;
break;
}
if (newWidget)
{
std::vector<std::string> enumValues;
const google::protobuf::EnumDescriptor *descriptor = value->type();
if (!descriptor)
break;
for (int j = 0; j < descriptor->value_count(); ++j)
{
const google::protobuf::EnumValueDescriptor *valueDescriptor =
descriptor->value(j);
if (valueDescriptor)
enumValues.push_back(valueDescriptor->name());
}
configChildWidget =
this->CreateEnumWidget(name, enumValues, _level);
if (!configChildWidget)
{
gzerr << "Error creating an enum widget for '" << name << "'"
<< std::endl;
break;
}
newFieldWidget = configChildWidget;
}
this->UpdateEnumWidget(configChildWidget, value->name());
break;
}
default:
break;
}
// Style widgets without parent (level 0)
if (newFieldWidget && _level == 0 &&
!qobject_cast<GroupWidget *>(newFieldWidget))
{
newFieldWidget->setStyleSheet(
"QWidget\
{\
background-color: " + this->bgColors[0] +
"}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox, QPlainTextEdit\
{\
background-color: " + this->widgetColors[0] +
"}");
}
if (newWidget && newFieldWidget)
{
newWidgets.push_back(newFieldWidget);
// store the newly created widget in a map with a unique scoped name.
if (qobject_cast<GroupWidget *>(newFieldWidget))
{
GroupWidget *groupWidget =
qobject_cast<GroupWidget *>(newFieldWidget);
ConfigChildWidget *childWidget = qobject_cast<ConfigChildWidget *>(
groupWidget->childWidget);
this->AddConfigChildWidget(scopedName, childWidget);
}
else if (qobject_cast<ConfigChildWidget *>(newFieldWidget))
{
this->AddConfigChildWidget(scopedName,
qobject_cast<ConfigChildWidget *>(newFieldWidget));
}
}
}
}
if (!newWidgets.empty())
{
// create a group box to hold child widgets.
QGroupBox *widget = new QGroupBox();
QVBoxLayout *widgetLayout = new QVBoxLayout;
for (unsigned int i = 0; i < newWidgets.size(); ++i)
{
widgetLayout->addWidget(newWidgets[i]);
}
widgetLayout->setContentsMargins(0, 0, 0, 0);
widgetLayout->setSpacing(0);
widgetLayout->setAlignment(Qt::AlignTop);
widget->setLayout(widgetLayout);
return widget;
}
return NULL;
}
/////////////////////////////////////////////////
GroupWidget *ConfigWidget::CreateGroupWidget(const std::string &_name,
ConfigChildWidget *_childWidget, const int _level)
{
// Button label
QLabel *buttonLabel = new QLabel(
tr(this->HumanReadableKey(_name).c_str()));
buttonLabel->setToolTip(tr(_name.c_str()));
// Button icon
QCheckBox *buttonIcon = new QCheckBox();
buttonIcon->setChecked(true);
buttonIcon->setStyleSheet(
"QCheckBox::indicator::unchecked {\
image: url(:/images/right_arrow.png);\
}\
QCheckBox::indicator::checked {\
image: url(:/images/down_arrow.png);\
}");
// Button layout
QHBoxLayout *buttonLayout = new QHBoxLayout();
buttonLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
buttonLayout->addWidget(buttonLabel);
buttonLayout->addWidget(buttonIcon);
buttonLayout->setAlignment(buttonIcon, Qt::AlignRight);
// Button frame
QFrame *buttonFrame = new QFrame();
buttonFrame->setFrameStyle(QFrame::Box);
buttonFrame->setLayout(buttonLayout);
// Set color for top level button
if (_level == 0)
{
buttonFrame->setStyleSheet(
"QWidget\
{\
background-color: " + this->bgColors[0] +
"}");
}
// Child widgets are contained in a group box which can be collapsed
GroupWidget *groupWidget = new GroupWidget;
groupWidget->setStyleSheet(
"QGroupBox {\
border : 0;\
margin : 0;\
padding : 0;\
}");
connect(buttonIcon, SIGNAL(toggled(bool)), groupWidget, SLOT(Toggle(bool)));
// Set the child widget
groupWidget->childWidget = _childWidget;
_childWidget->groupWidget = groupWidget;
_childWidget->setContentsMargins(0, 0, 0, 0);
// Set color for children
if (_level == 0)
{
_childWidget->setStyleSheet(
"QWidget\
{\
background-color: " + this->bgColors[1] +
"}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox, QPlainTextEdit\
{\
background-color: " + this->widgetColors[1] +
"}");
}
else if (_level == 1)
{
_childWidget->setStyleSheet(
"QWidget\
{\
background-color: " + this->bgColors[2] +
"}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox, QPlainTextEdit\
{\
background-color: " + this->widgetColors[2] +
"}");
}
else if (_level == 2)
{
_childWidget->setStyleSheet(
"QWidget\
{\
background-color: " + this->bgColors[3] +
"}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox, QPlainTextEdit\
{\
background-color: " + this->widgetColors[3] +
"}");
}
// Group Layout
QGridLayout *configGroupLayout = new QGridLayout;
configGroupLayout->setContentsMargins(0, 0, 0, 0);
configGroupLayout->setSpacing(0);
configGroupLayout->addWidget(buttonFrame, 0, 0);
configGroupLayout->addWidget(_childWidget, 1, 0);
groupWidget->setLayout(configGroupLayout);
return groupWidget;
}
/////////////////////////////////////////////////
ignition::math::Vector3d ConfigWidget::ParseVector3d(
const google::protobuf::Message *_msg) const
{
ignition::math::Vector3d vec3;
const google::protobuf::Descriptor *valueDescriptor = _msg->GetDescriptor();
std::vector<double> values;
for (unsigned int i = 0; i < 3; ++i)
{
const google::protobuf::FieldDescriptor *valueField =
valueDescriptor->field(i);
values.push_back(_msg->GetReflection()->GetDouble(*_msg, valueField));
}
vec3.X(values[0]);
vec3.Y(values[1]);
vec3.Z(values[2]);
return vec3;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateUIntWidget(const std::string &_key,
const int _level)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Label
QLabel *keyLabel = new QLabel(tr(this->HumanReadableKey(_key).c_str()));
keyLabel->setToolTip(tr(_key.c_str()));
// SpinBox
QSpinBox *valueSpinBox = new QSpinBox(widget);
valueSpinBox->setRange(0, 1e8);
valueSpinBox->setAlignment(Qt::AlignRight);
connect(valueSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnUIntValueChanged()));
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
if (_level != 0)
{
widgetLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
}
widgetLayout->addWidget(keyLabel);
widgetLayout->addWidget(valueSpinBox);
// ChildWidget
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(valueSpinBox);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateIntWidget(const std::string &_key,
const int _level)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Label
QLabel *keyLabel = new QLabel(tr(this->HumanReadableKey(_key).c_str()));
keyLabel->setToolTip(tr(_key.c_str()));
// SpinBox
QSpinBox *valueSpinBox = new QSpinBox(widget);
valueSpinBox->setRange(-1e8, 1e8);
valueSpinBox->setAlignment(Qt::AlignRight);
connect(valueSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnIntValueChanged()));
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
if (_level != 0)
{
widgetLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
}
widgetLayout->addWidget(keyLabel);
widgetLayout->addWidget(valueSpinBox);
// ChildWidget
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(valueSpinBox);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateDoubleWidget(const std::string &_key,
const int _level)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Label
QLabel *keyLabel = new QLabel(tr(this->HumanReadableKey(_key).c_str()));
keyLabel->setToolTip(tr(_key.c_str()));
// SpinBox
double min = 0;
double max = 0;
this->RangeFromKey(_key, min, max);
QDoubleSpinBox *valueSpinBox = new QDoubleSpinBox(widget);
valueSpinBox->setRange(min, max);
valueSpinBox->setSingleStep(0.01);
valueSpinBox->setDecimals(8);
valueSpinBox->setAlignment(Qt::AlignRight);
connect(valueSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnDoubleValueChanged()));
// Unit
std::string jointType = this->EnumWidgetValue("type");
std::string unit = this->UnitFromKey(_key, jointType);
QLabel *unitLabel = new QLabel();
unitLabel->setMaximumWidth(40);
unitLabel->setText(QString::fromStdString(unit));
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
if (_level != 0)
{
widgetLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
}
widgetLayout->addWidget(keyLabel);
widgetLayout->addWidget(valueSpinBox);
if (unitLabel->text() != "")
widgetLayout->addWidget(unitLabel);
// ChildWidget
widget->key = _key;
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(valueSpinBox);
widget->mapWidgetToUnit[valueSpinBox] = unitLabel;
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateStringWidget(const std::string &_key,
const int _level, const std::string &_type)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Label
QLabel *keyLabel = new QLabel(tr(this->HumanReadableKey(_key).c_str()));
keyLabel->setToolTip(tr(_key.c_str()));
// Line or Text Edit based on key
QWidget *valueEdit;
if (_type == "plain")
{
valueEdit = new QPlainTextEdit(widget);
valueEdit->setMinimumHeight(50);
// QPlainTextEdit's don't have editingFinished signals
}
else if (_type == "line")
{
valueEdit = new QLineEdit(widget);
connect(valueEdit, SIGNAL(editingFinished()), this,
SLOT(OnStringValueChanged()));
}
else
{
gzerr << "Unknown type [" << _type << "]. Not creating string widget" <<
std::endl;
return NULL;
}
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
if (_level != 0)
{
widgetLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
}
widgetLayout->addWidget(keyLabel);
widgetLayout->addWidget(valueEdit);
// ChildWidget
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(valueEdit);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateBoolWidget(const std::string &_key,
const int _level)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Label
QLabel *keyLabel = new QLabel(tr(this->HumanReadableKey(_key).c_str()));
keyLabel->setToolTip(tr(_key.c_str()));
// Buttons
QRadioButton *valueTrueRadioButton = new QRadioButton(widget);
valueTrueRadioButton->setText(tr("True"));
connect(valueTrueRadioButton, SIGNAL(toggled(bool)), this,
SLOT(OnBoolValueChanged()));
QRadioButton *valueFalseRadioButton = new QRadioButton(widget);
valueFalseRadioButton->setText(tr("False"));
connect(valueFalseRadioButton, SIGNAL(toggled(bool)), this,
SLOT(OnBoolValueChanged()));
QButtonGroup *boolButtonGroup = new QButtonGroup;
boolButtonGroup->addButton(valueTrueRadioButton);
boolButtonGroup->addButton(valueFalseRadioButton);
boolButtonGroup->setExclusive(true);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(valueTrueRadioButton);
buttonLayout->addWidget(valueFalseRadioButton);
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
if (_level != 0)
{
widgetLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
}
widgetLayout->addWidget(keyLabel);
widgetLayout->addLayout(buttonLayout);
// ChildWidget
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(valueTrueRadioButton);
widget->widgets.push_back(valueFalseRadioButton);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateVector3dWidget(
const std::string &_key, const int _level)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Presets
auto presetsCombo = new QComboBox(widget);
presetsCombo->addItem("Custom", 0);
presetsCombo->addItem(" X", 1);
presetsCombo->addItem("-X", 2);
presetsCombo->addItem(" Y", 3);
presetsCombo->addItem("-Y", 4);
presetsCombo->addItem(" Z", 5);
presetsCombo->addItem("-Z", 6);
presetsCombo->setMinimumWidth(80);
connect(presetsCombo, SIGNAL(currentIndexChanged(const int)), this,
SLOT(OnVector3dPresetChanged(const int)));
// Labels
QLabel *vecXLabel = new QLabel(tr("X"));
QLabel *vecYLabel = new QLabel(tr("Y"));
QLabel *vecZLabel = new QLabel(tr("Z"));
vecXLabel->setToolTip(tr("x"));
vecYLabel->setToolTip(tr("y"));
vecZLabel->setToolTip(tr("z"));
// SpinBoxes
double min = 0;
double max = 0;
this->RangeFromKey(_key, min, max);
QDoubleSpinBox *vecXSpinBox = new QDoubleSpinBox(widget);
vecXSpinBox->setRange(min, max);
vecXSpinBox->setSingleStep(0.01);
vecXSpinBox->setDecimals(6);
vecXSpinBox->setAlignment(Qt::AlignRight);
vecXSpinBox->setMaximumWidth(100);
connect(vecXSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnVector3dValueChanged()));
QDoubleSpinBox *vecYSpinBox = new QDoubleSpinBox(widget);
vecYSpinBox->setRange(min, max);
vecYSpinBox->setSingleStep(0.01);
vecYSpinBox->setDecimals(6);
vecYSpinBox->setAlignment(Qt::AlignRight);
vecYSpinBox->setMaximumWidth(100);
connect(vecYSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnVector3dValueChanged()));
QDoubleSpinBox *vecZSpinBox = new QDoubleSpinBox(widget);
vecZSpinBox->setRange(min, max);
vecZSpinBox->setSingleStep(0.01);
vecZSpinBox->setDecimals(6);
vecZSpinBox->setAlignment(Qt::AlignRight);
vecZSpinBox->setMaximumWidth(100);
connect(vecZSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnVector3dValueChanged()));
// This is inside a group
int level = _level + 1;
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
widgetLayout->addItem(new QSpacerItem(20*level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
widgetLayout->addWidget(presetsCombo);
widgetLayout->addWidget(vecXLabel);
widgetLayout->addWidget(vecXSpinBox);
widgetLayout->addWidget(vecYLabel);
widgetLayout->addWidget(vecYSpinBox);
widgetLayout->addWidget(vecZLabel);
widgetLayout->addWidget(vecZSpinBox);
widgetLayout->setAlignment(vecXLabel, Qt::AlignRight);
widgetLayout->setAlignment(vecYLabel, Qt::AlignRight);
widgetLayout->setAlignment(vecZLabel, Qt::AlignRight);
// ChildWidget
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(vecXSpinBox);
widget->widgets.push_back(vecYSpinBox);
widget->widgets.push_back(vecZSpinBox);
widget->widgets.push_back(presetsCombo);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateColorWidget(const std::string &_key,
const int _level)
{
// ChildWidget
ConfigChildWidget *widget = new ConfigChildWidget();
// Labels
QLabel *colorRLabel = new QLabel(tr("R"));
QLabel *colorGLabel = new QLabel(tr("G"));
QLabel *colorBLabel = new QLabel(tr("B"));
QLabel *colorALabel = new QLabel(tr("A"));
colorRLabel->setToolTip(tr("r"));
colorGLabel->setToolTip(tr("g"));
colorBLabel->setToolTip(tr("b"));
colorALabel->setToolTip(tr("a"));
// SpinBoxes
double min = 0;
double max = 0;
this->RangeFromKey(_key, min, max);
QDoubleSpinBox *colorRSpinBox = new QDoubleSpinBox(widget);
colorRSpinBox->setRange(0, 1.0);
colorRSpinBox->setSingleStep(0.1);
colorRSpinBox->setDecimals(3);
colorRSpinBox->setAlignment(Qt::AlignRight);
colorRSpinBox->setMaximumWidth(10);
connect(colorRSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnColorValueChanged()));
QDoubleSpinBox *colorGSpinBox = new QDoubleSpinBox(widget);
colorGSpinBox->setRange(0, 1.0);
colorGSpinBox->setSingleStep(0.1);
colorGSpinBox->setDecimals(3);
colorGSpinBox->setAlignment(Qt::AlignRight);
colorGSpinBox->setMaximumWidth(10);
connect(colorGSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnColorValueChanged()));
QDoubleSpinBox *colorBSpinBox = new QDoubleSpinBox(widget);
colorBSpinBox->setRange(0, 1.0);
colorBSpinBox->setSingleStep(0.1);
colorBSpinBox->setDecimals(3);
colorBSpinBox->setAlignment(Qt::AlignRight);
colorBSpinBox->setMaximumWidth(10);
connect(colorBSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnColorValueChanged()));
QDoubleSpinBox *colorASpinBox = new QDoubleSpinBox(widget);
colorASpinBox->setRange(0, 1.0);
colorASpinBox->setSingleStep(0.1);
colorASpinBox->setDecimals(3);
colorASpinBox->setAlignment(Qt::AlignRight);
colorASpinBox->setMaximumWidth(10);
connect(colorASpinBox, SIGNAL(editingFinished()), this,
SLOT(OnColorValueChanged()));
// This is inside a group
int level = _level + 1;
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
widgetLayout->addItem(new QSpacerItem(20*level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
widgetLayout->addWidget(colorRLabel);
widgetLayout->addWidget(colorRSpinBox);
widgetLayout->addWidget(colorGLabel);
widgetLayout->addWidget(colorGSpinBox);
widgetLayout->addWidget(colorBLabel);
widgetLayout->addWidget(colorBSpinBox);
widgetLayout->addWidget(colorALabel);
widgetLayout->addWidget(colorASpinBox);
widgetLayout->setAlignment(colorRLabel, Qt::AlignRight);
widgetLayout->setAlignment(colorGLabel, Qt::AlignRight);
widgetLayout->setAlignment(colorBLabel, Qt::AlignRight);
widgetLayout->setAlignment(colorALabel, Qt::AlignRight);
// ChildWidget
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
widget->widgets.push_back(colorRSpinBox);
widget->widgets.push_back(colorGSpinBox);
widget->widgets.push_back(colorBSpinBox);
widget->widgets.push_back(colorASpinBox);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreatePoseWidget(const std::string &/*_key*/,
const int _level)
{
// Labels
std::vector<std::string> elements;
elements.push_back("x");
elements.push_back("y");
elements.push_back("z");
elements.push_back("roll");
elements.push_back("pitch");
elements.push_back("yaw");
// This is inside a group
int level = _level+1;
// Layout
QGridLayout *widgetLayout = new QGridLayout;
widgetLayout->setColumnStretch(3, 1);
widgetLayout->addItem(new QSpacerItem(20*level, 1, QSizePolicy::Fixed,
QSizePolicy::Fixed), 0, 0);
// ChildWidget
double min = 0;
double max = 0;
this->RangeFromKey("", min, max);
ConfigChildWidget *widget = new ConfigChildWidget();
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
for (unsigned int i = 0; i < elements.size(); ++i)
{
QDoubleSpinBox *spin = new QDoubleSpinBox(widget);
connect(spin, SIGNAL(editingFinished()), this, SLOT(OnPoseValueChanged()));
widget->widgets.push_back(spin);
spin->setRange(min, max);
spin->setSingleStep(0.01);
spin->setDecimals(6);
spin->setAlignment(Qt::AlignRight);
spin->setMaximumWidth(100);
QLabel *label = new QLabel(this->HumanReadableKey(elements[i]).c_str());
label->setToolTip(tr(elements[i].c_str()));
if (i == 0)
label->setStyleSheet("QLabel{color: " + this->redColor + ";}");
else if (i == 1)
label->setStyleSheet("QLabel{color: " + this->greenColor + ";}");
else if (i == 2)
label->setStyleSheet("QLabel{color:" + this->blueColor + ";}");
QLabel *unitLabel = new QLabel();
unitLabel->setMaximumWidth(40);
unitLabel->setMinimumWidth(40);
if (i < 3)
unitLabel->setText(QString::fromStdString(this->UnitFromKey("pos")));
else
unitLabel->setText(QString::fromStdString(this->UnitFromKey("rot")));
widgetLayout->addWidget(label, i%3, std::floor(i/3)*3+1);
widgetLayout->addWidget(spin, i%3, std::floor(i/3)*3+2);
widgetLayout->addWidget(unitLabel, i%3, std::floor(i/3)*3+3);
widgetLayout->setAlignment(label, Qt::AlignLeft);
widgetLayout->setAlignment(spin, Qt::AlignLeft);
widgetLayout->setAlignment(unitLabel, Qt::AlignLeft);
}
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateGeometryWidget(
const std::string &/*_key*/, const int _level)
{
// ChildWidget
GeometryConfigWidget *widget = new GeometryConfigWidget;
// Geometry ComboBox
QLabel *geometryLabel = new QLabel(tr("Geometry"));
geometryLabel->setToolTip(tr("geometry"));
QComboBox *geometryComboBox = new QComboBox(widget);
geometryComboBox->addItem(tr("box"));
geometryComboBox->addItem(tr("cylinder"));
geometryComboBox->addItem(tr("sphere"));
geometryComboBox->addItem(tr("mesh"));
geometryComboBox->addItem(tr("polyline"));
connect(geometryComboBox, SIGNAL(currentIndexChanged(const int)), this,
SLOT(OnGeometryValueChanged(const int)));
// Size XYZ
double min = 0;
double max = 0;
this->RangeFromKey("length", min, max);
QDoubleSpinBox *geomSizeXSpinBox = new QDoubleSpinBox(widget);
geomSizeXSpinBox->setRange(min, max);
geomSizeXSpinBox->setSingleStep(0.01);
geomSizeXSpinBox->setDecimals(6);
geomSizeXSpinBox->setValue(1.000);
geomSizeXSpinBox->setAlignment(Qt::AlignRight);
geomSizeXSpinBox->setMaximumWidth(100);
connect(geomSizeXSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnGeometryValueChanged()));
QDoubleSpinBox *geomSizeYSpinBox = new QDoubleSpinBox(widget);
geomSizeYSpinBox->setRange(min, max);
geomSizeYSpinBox->setSingleStep(0.01);
geomSizeYSpinBox->setDecimals(6);
geomSizeYSpinBox->setValue(1.000);
geomSizeYSpinBox->setAlignment(Qt::AlignRight);
geomSizeYSpinBox->setMaximumWidth(100);
connect(geomSizeYSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnGeometryValueChanged()));
QDoubleSpinBox *geomSizeZSpinBox = new QDoubleSpinBox(widget);
geomSizeZSpinBox->setRange(min, max);
geomSizeZSpinBox->setSingleStep(0.01);
geomSizeZSpinBox->setDecimals(6);
geomSizeZSpinBox->setValue(1.000);
geomSizeZSpinBox->setAlignment(Qt::AlignRight);
geomSizeZSpinBox->setMaximumWidth(100);
connect(geomSizeZSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnGeometryValueChanged()));
QLabel *geomSizeXLabel = new QLabel(tr("X"));
QLabel *geomSizeYLabel = new QLabel(tr("Y"));
QLabel *geomSizeZLabel = new QLabel(tr("Z"));
geomSizeXLabel->setStyleSheet("QLabel{color: " + this->redColor + ";}");
geomSizeYLabel->setStyleSheet("QLabel{color: " + this->greenColor + ";}");
geomSizeZLabel->setStyleSheet("QLabel{color: " + this->blueColor + ";}");
geomSizeXLabel->setToolTip(tr("x"));
geomSizeYLabel->setToolTip(tr("y"));
geomSizeZLabel->setToolTip(tr("z"));
std::string unit = this->UnitFromKey("length");
QLabel *geomSizeXUnitLabel = new QLabel(QString::fromStdString(unit));
QLabel *geomSizeYUnitLabel = new QLabel(QString::fromStdString(unit));
QLabel *geomSizeZUnitLabel = new QLabel(QString::fromStdString(unit));
QHBoxLayout *geomSizeLayout = new QHBoxLayout;
geomSizeLayout->addWidget(geomSizeXLabel);
geomSizeLayout->addWidget(geomSizeXSpinBox);
geomSizeLayout->addWidget(geomSizeXUnitLabel);
geomSizeLayout->addWidget(geomSizeYLabel);
geomSizeLayout->addWidget(geomSizeYSpinBox);
geomSizeLayout->addWidget(geomSizeYUnitLabel);
geomSizeLayout->addWidget(geomSizeZLabel);
geomSizeLayout->addWidget(geomSizeZSpinBox);
geomSizeLayout->addWidget(geomSizeZUnitLabel);
geomSizeLayout->setAlignment(geomSizeXLabel, Qt::AlignRight);
geomSizeLayout->setAlignment(geomSizeYLabel, Qt::AlignRight);
geomSizeLayout->setAlignment(geomSizeZLabel, Qt::AlignRight);
// Uri
QLabel *geomFilenameLabel = new QLabel(tr("Uri"));
geomFilenameLabel->setToolTip(tr("uri"));
QLineEdit *geomFilenameLineEdit = new QLineEdit(widget);
connect(geomFilenameLineEdit, SIGNAL(editingFinished()), this,
SLOT(OnGeometryValueChanged()));
QPushButton *geomFilenameButton = new QPushButton(tr("..."));
geomFilenameButton->setMaximumWidth(30);
QHBoxLayout *geomFilenameLayout = new QHBoxLayout;
geomFilenameLayout->addWidget(geomFilenameLabel);
geomFilenameLayout->addWidget(geomFilenameLineEdit);
geomFilenameLayout->addWidget(geomFilenameButton);
QVBoxLayout *geomSizeFilenameLayout = new QVBoxLayout;
geomSizeFilenameLayout->addLayout(geomSizeLayout);
geomSizeFilenameLayout->addLayout(geomFilenameLayout);
QWidget *geomSizeWidget = new QWidget(widget);
geomSizeWidget->setLayout(geomSizeFilenameLayout);
// Radius / Length
QLabel *geomRadiusLabel = new QLabel(tr("Radius"));
QLabel *geomLengthLabel = new QLabel(tr("Length"));
QLabel *geomRadiusUnitLabel = new QLabel(QString::fromStdString(unit));
QLabel *geomLengthUnitLabel = new QLabel(QString::fromStdString(unit));
geomRadiusLabel->setToolTip(tr("radius"));
geomLengthLabel->setToolTip(tr("length"));
QDoubleSpinBox *geomRadiusSpinBox = new QDoubleSpinBox(widget);
geomRadiusSpinBox->setRange(min, max);
geomRadiusSpinBox->setSingleStep(0.01);
geomRadiusSpinBox->setDecimals(6);
geomRadiusSpinBox->setValue(0.500);
geomRadiusSpinBox->setAlignment(Qt::AlignRight);
geomRadiusSpinBox->setMaximumWidth(100);
connect(geomRadiusSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnGeometryValueChanged()));
QDoubleSpinBox *geomLengthSpinBox = new QDoubleSpinBox(widget);
geomLengthSpinBox->setRange(min, max);
geomLengthSpinBox->setSingleStep(0.01);
geomLengthSpinBox->setDecimals(6);
geomLengthSpinBox->setValue(1.000);
geomLengthSpinBox->setAlignment(Qt::AlignRight);
geomLengthSpinBox->setMaximumWidth(100);
connect(geomLengthSpinBox, SIGNAL(editingFinished()), this,
SLOT(OnGeometryValueChanged()));
QHBoxLayout *geomRLLayout = new QHBoxLayout;
geomRLLayout->addWidget(geomRadiusLabel);
geomRLLayout->addWidget(geomRadiusSpinBox);
geomRLLayout->addWidget(geomRadiusUnitLabel);
geomRLLayout->addWidget(geomLengthLabel);
geomRLLayout->addWidget(geomLengthSpinBox);
geomRLLayout->addWidget(geomLengthUnitLabel);
geomRLLayout->setAlignment(geomRadiusLabel, Qt::AlignRight);
geomRLLayout->setAlignment(geomLengthLabel, Qt::AlignRight);
QWidget *geomRLWidget = new QWidget;
geomRLWidget->setLayout(geomRLLayout);
// Dimensions
QStackedWidget *geomDimensionWidget = new QStackedWidget(widget);
geomDimensionWidget->insertWidget(0, geomSizeWidget);
geomDimensionWidget->insertWidget(1, geomRLWidget);
geomDimensionWidget->setCurrentIndex(0);
geomDimensionWidget->setSizePolicy(
QSizePolicy::Minimum, QSizePolicy::Minimum);
// This is inside a group
int level = _level + 1;
// Layout
QGridLayout *widgetLayout = new QGridLayout;
widgetLayout->addItem(new QSpacerItem(20*level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed), 0, 0);
widgetLayout->addWidget(geometryLabel, 0, 1);
widgetLayout->addWidget(geometryComboBox, 0, 2, 1, 2);
widgetLayout->addWidget(geomDimensionWidget, 2, 1, 1, 3);
// ChildWidget
widget->setFrameStyle(QFrame::Box);
widget->geomDimensionWidget = geomDimensionWidget;
widget->geomLengthSpinBox = geomLengthSpinBox;
widget->geomLengthLabel = geomLengthLabel;
widget->geomLengthUnitLabel = geomLengthUnitLabel;
widget->geomFilenameLabel = geomFilenameLabel;
widget->geomFilenameLineEdit = geomFilenameLineEdit;
widget->geomFilenameButton = geomFilenameButton;
geomFilenameLabel->setVisible(false);
geomFilenameLineEdit->setVisible(false);
geomFilenameButton->setVisible(false);
connect(geometryComboBox, SIGNAL(currentIndexChanged(const QString)),
widget, SLOT(GeometryChanged(const QString)));
connect(geomFilenameButton, SIGNAL(clicked()), widget, SLOT(OnSelectFile()));
widget->setLayout(widgetLayout);
widget->widgets.push_back(geometryComboBox);
widget->widgets.push_back(geomSizeXSpinBox);
widget->widgets.push_back(geomSizeYSpinBox);
widget->widgets.push_back(geomSizeZSpinBox);
widget->widgets.push_back(geomRadiusSpinBox);
widget->widgets.push_back(geomLengthSpinBox);
widget->widgets.push_back(geomFilenameLineEdit);
widget->widgets.push_back(geomFilenameButton);
return widget;
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::CreateEnumWidget(
const std::string &_key, const std::vector<std::string> &_values,
const int _level)
{
// Label
QLabel *enumLabel = new QLabel(this->HumanReadableKey(_key).c_str());
enumLabel->setToolTip(tr(_key.c_str()));
// ComboBox
QComboBox *enumComboBox = new QComboBox;
for (unsigned int i = 0; i < _values.size(); ++i)
enumComboBox->addItem(tr(_values[i].c_str()));
// Layout
QHBoxLayout *widgetLayout = new QHBoxLayout;
if (_level != 0)
{
widgetLayout->addItem(new QSpacerItem(20*_level, 1,
QSizePolicy::Fixed, QSizePolicy::Fixed));
}
widgetLayout->addWidget(enumLabel);
widgetLayout->addWidget(enumComboBox);
// ChildWidget
EnumConfigWidget *widget = new EnumConfigWidget();
widget->setLayout(widgetLayout);
widget->setFrameStyle(QFrame::Box);
connect(enumComboBox, SIGNAL(currentIndexChanged(const QString &)),
widget, SLOT(EnumChanged(const QString &)));
widget->widgets.push_back(enumComboBox);
// connect enum config widget event so that we can fire another
// event from ConfigWidget that has the name of this field
connect(widget,
SIGNAL(EnumValueChanged(const QString &)), this,
SLOT(OnEnumValueChanged(const QString &)));
return widget;
}
/////////////////////////////////////////////////
void ConfigWidget::UpdateMsg(google::protobuf::Message *_msg,
const std::string &_name)
{
const google::protobuf::Descriptor *d = _msg->GetDescriptor();
if (!d)
return;
unsigned int count = d->field_count();
for (unsigned int i = 0; i < count ; ++i)
{
const google::protobuf::FieldDescriptor *field = d->field(i);
if (!field)
return;
const google::protobuf::Reflection *ref = _msg->GetReflection();
if (!ref)
return;
std::string name = field->name();
// Update each field in the message
// TODO update repeated fields
if (!field->is_repeated() /*&& ref->HasField(*_msg, field)*/)
{
std::string scopedName = _name.empty() ? name : _name + "::" + name;
if (this->dataPtr->configWidgets.find(scopedName) ==
this->dataPtr->configWidgets.end())
continue;
// don't update msgs field that are associated with read-only widgets
if (this->WidgetReadOnly(scopedName))
continue;
ConfigChildWidget *childWidget = this->dataPtr->configWidgets[scopedName];
switch (field->type())
{
case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
{
QDoubleSpinBox *valueSpinBox =
qobject_cast<QDoubleSpinBox *>(childWidget->widgets[0]);
ref->SetDouble(_msg, field, valueSpinBox->value());
break;
}
case google::protobuf::FieldDescriptor::TYPE_FLOAT:
{
QDoubleSpinBox *valueSpinBox =
qobject_cast<QDoubleSpinBox *>(childWidget->widgets[0]);
ref->SetFloat(_msg, field, valueSpinBox->value());
break;
}
case google::protobuf::FieldDescriptor::TYPE_INT64:
{
QSpinBox *valueSpinBox =
qobject_cast<QSpinBox *>(childWidget->widgets[0]);
ref->SetInt64(_msg, field, valueSpinBox->value());
break;
}
case google::protobuf::FieldDescriptor::TYPE_UINT64:
{
QSpinBox *valueSpinBox =
qobject_cast<QSpinBox *>(childWidget->widgets[0]);
ref->SetUInt64(_msg, field, valueSpinBox->value());
break;
}
case google::protobuf::FieldDescriptor::TYPE_INT32:
{
QSpinBox *valueSpinBox =
qobject_cast<QSpinBox *>(childWidget->widgets[0]);
ref->SetInt32(_msg, field, valueSpinBox->value());
break;
}
case google::protobuf::FieldDescriptor::TYPE_UINT32:
{
QSpinBox *valueSpinBox =
qobject_cast<QSpinBox *>(childWidget->widgets[0]);
ref->SetUInt32(_msg, field, valueSpinBox->value());
break;
}
case google::protobuf::FieldDescriptor::TYPE_BOOL:
{
QRadioButton *valueRadioButton =
qobject_cast<QRadioButton *>(childWidget->widgets[0]);
ref->SetBool(_msg, field, valueRadioButton->isChecked());
break;
}
case google::protobuf::FieldDescriptor::TYPE_STRING:
{
if (qobject_cast<QLineEdit *>(childWidget->widgets[0]))
{
QLineEdit *valueLineEdit =
qobject_cast<QLineEdit *>(childWidget->widgets[0]);
ref->SetString(_msg, field, valueLineEdit->text().toStdString());
}
else if (qobject_cast<QPlainTextEdit *>(childWidget->widgets[0]))
{
QPlainTextEdit *valueTextEdit =
qobject_cast<QPlainTextEdit *>(childWidget->widgets[0]);
ref->SetString(_msg, field,
valueTextEdit->toPlainText().toStdString());
}
break;
}
case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
{
google::protobuf::Message *valueMsg =
(ref->MutableMessage(_msg, field));
// update geometry msg field
if (field->message_type()->name() == "Geometry")
{
// manually retrieve values from widgets in order to update
// the message fields.
QComboBox *valueComboBox =
qobject_cast<QComboBox *>(childWidget->widgets[0]);
std::string geomType = valueComboBox->currentText().toStdString();
const google::protobuf::Descriptor *valueDescriptor =
valueMsg->GetDescriptor();
const google::protobuf::Reflection *geomReflection =
valueMsg->GetReflection();
const google::protobuf::FieldDescriptor *typeField =
valueDescriptor->FindFieldByName("type");
const google::protobuf::EnumDescriptor *typeEnumDescriptor =
typeField->enum_type();
if (geomType == "box" || geomType == "mesh")
{
double sizeX = qobject_cast<QDoubleSpinBox *>(
childWidget->widgets[1])->value();
double sizeY = qobject_cast<QDoubleSpinBox *>(
childWidget->widgets[2])->value();
double sizeZ = qobject_cast<QDoubleSpinBox *>(
childWidget->widgets[3])->value();
ignition::math::Vector3d geomSize(sizeX, sizeY, sizeZ);
// set type
std::string typeStr =
QString(tr(geomType.c_str())).toUpper().toStdString();
const google::protobuf::EnumValueDescriptor *geometryType =
typeEnumDescriptor->FindValueByName(typeStr);
geomReflection->SetEnum(valueMsg, typeField, geometryType);
// set dimensions
const google::protobuf::FieldDescriptor *geomFieldDescriptor =
valueDescriptor->FindFieldByName(geomType);
google::protobuf::Message *geomValueMsg =
geomReflection->MutableMessage(valueMsg, geomFieldDescriptor);
int fieldIdx = (geomType == "box") ? 0 : 1;
google::protobuf::Message *geomDimensionMsg =
geomValueMsg->GetReflection()->MutableMessage(geomValueMsg,
geomValueMsg->GetDescriptor()->field(fieldIdx));
this->UpdateVector3dMsg(geomDimensionMsg, geomSize);
if (geomType == "mesh")
{
std::string uri = qobject_cast<QLineEdit *>(
childWidget->widgets[6])->text().toStdString();
const google::protobuf::FieldDescriptor *uriFieldDescriptor =
geomValueMsg->GetDescriptor()->field(0);
geomValueMsg->GetReflection()->SetString(geomValueMsg,
uriFieldDescriptor, uri);
}
}
else if (geomType == "cylinder")
{
double radius = qobject_cast<QDoubleSpinBox *>(
childWidget->widgets[4])->value();
double length = qobject_cast<QDoubleSpinBox *>(
childWidget->widgets[5])->value();
// set type
const google::protobuf::EnumValueDescriptor *geometryType =
typeEnumDescriptor->FindValueByName("CYLINDER");
geomReflection->SetEnum(valueMsg, typeField, geometryType);
// set radius and length
const google::protobuf::FieldDescriptor *geomFieldDescriptor =
valueDescriptor->FindFieldByName(geomType);
google::protobuf::Message *geomValueMsg =
geomReflection->MutableMessage(valueMsg, geomFieldDescriptor);
const google::protobuf::FieldDescriptor *geomRadiusField =
geomValueMsg->GetDescriptor()->field(0);
geomValueMsg->GetReflection()->SetDouble(geomValueMsg,
geomRadiusField, radius);
const google::protobuf::FieldDescriptor *geomLengthField =
geomValueMsg->GetDescriptor()->field(1);
geomValueMsg->GetReflection()->SetDouble(geomValueMsg,
geomLengthField, length);
}
else if (geomType == "sphere")
{
double radius = qobject_cast<QDoubleSpinBox *>(
childWidget->widgets[4])->value();
// set type
const google::protobuf::EnumValueDescriptor *geometryType =
typeEnumDescriptor->FindValueByName("SPHERE");
geomReflection->SetEnum(valueMsg, typeField, geometryType);
// set radius
const google::protobuf::FieldDescriptor *geomFieldDescriptor =
valueDescriptor->FindFieldByName(geomType);
google::protobuf::Message *geomValueMsg =
geomReflection->MutableMessage(valueMsg, geomFieldDescriptor);
const google::protobuf::FieldDescriptor *geomRadiusField =
geomValueMsg->GetDescriptor()->field(0);
geomValueMsg->GetReflection()->SetDouble(geomValueMsg,
geomRadiusField, radius);
}
else if (geomType == "polyline")
{
const google::protobuf::EnumValueDescriptor *geometryType =
typeEnumDescriptor->FindValueByName("POLYLINE");
geomReflection->SetEnum(valueMsg, typeField, geometryType);
}
}
// update pose msg field
else if (field->message_type()->name() == "Pose")
{
const google::protobuf::Descriptor *valueDescriptor =
valueMsg->GetDescriptor();
int valueMsgFieldCount = valueDescriptor->field_count();
// loop through the message fields to update:
// a vector3d field (position)
// and quaternion field (orientation)
for (int j = 0; j < valueMsgFieldCount ; ++j)
{
const google::protobuf::FieldDescriptor *valueField =
valueDescriptor->field(j);
if (valueField->type() !=
google::protobuf::FieldDescriptor::TYPE_MESSAGE)
continue;
if (valueField->message_type()->name() == "Vector3d")
{
// pos
google::protobuf::Message *posValueMsg =
valueMsg->GetReflection()->MutableMessage(
valueMsg, valueField);
std::vector<double> values;
for (unsigned int k = 0; k < 3; ++k)
{
QDoubleSpinBox *valueSpinBox =
qobject_cast<QDoubleSpinBox *>(childWidget->widgets[k]);
values.push_back(valueSpinBox->value());
}
ignition::math::Vector3d vec3(values[0], values[1], values[2]);
this->UpdateVector3dMsg(posValueMsg, vec3);
}
else if (valueField->message_type()->name() == "Quaternion")
{
// rot
google::protobuf::Message *quatValueMsg =
valueMsg->GetReflection()->MutableMessage(
valueMsg, valueField);
std::vector<double> rotValues;
for (unsigned int k = 3; k < 6; ++k)
{
QDoubleSpinBox *valueSpinBox =
qobject_cast<QDoubleSpinBox *>(childWidget->widgets[k]);
rotValues.push_back(valueSpinBox->value());
}
math::Quaternion quat(rotValues[0], rotValues[1], rotValues[2]);
std::vector<double> quatValues;
quatValues.push_back(quat.x);
quatValues.push_back(quat.y);
quatValues.push_back(quat.z);
quatValues.push_back(quat.w);
const google::protobuf::Descriptor *quatValueDescriptor =
quatValueMsg->GetDescriptor();
for (unsigned int k = 0; k < quatValues.size(); ++k)
{
const google::protobuf::FieldDescriptor *quatValueField =
quatValueDescriptor->field(k);
quatValueMsg->GetReflection()->SetDouble(quatValueMsg,
quatValueField, quatValues[k]);
}
}
}
}
else if (field->message_type()->name() == "Vector3d")
{
std::vector<double> values;
for (unsigned int j = 0; j < 3; ++j)
{
QDoubleSpinBox *valueSpinBox =
qobject_cast<QDoubleSpinBox *>(childWidget->widgets[j]);
values.push_back(valueSpinBox->value());
}
ignition::math::Vector3d vec3(values[0], values[1], values[2]);
this->UpdateVector3dMsg(valueMsg, vec3);
}
else if (field->message_type()->name() == "Color")
{
const google::protobuf::Descriptor *valueDescriptor =
valueMsg->GetDescriptor();
for (unsigned int j = 0; j < childWidget->widgets.size(); ++j)
{
QDoubleSpinBox *valueSpinBox =
qobject_cast<QDoubleSpinBox *>(childWidget->widgets[j]);
const google::protobuf::FieldDescriptor *valueField =
valueDescriptor->field(j);
valueMsg->GetReflection()->SetFloat(valueMsg, valueField,
valueSpinBox->value());
}
}
else
{
// update the message fields recursively
this->UpdateMsg(valueMsg, scopedName);
}
break;
}
case google::protobuf::FieldDescriptor::TYPE_ENUM:
{
QComboBox *valueComboBox =
qobject_cast<QComboBox *>(childWidget->widgets[0]);
if (valueComboBox)
{
std::string valueStr = valueComboBox->currentText().toStdString();
const google::protobuf::EnumDescriptor *enumDescriptor =
field->enum_type();
if (enumDescriptor)
{
const google::protobuf::EnumValueDescriptor *enumValue =
enumDescriptor->FindValueByName(valueStr);
if (enumValue)
ref->SetEnum(_msg, field, enumValue);
else
gzerr << "Unable to find enum value: '" << valueStr << "'"
<< std::endl;
}
}
break;
}
default:
break;
}
}
}
}
/////////////////////////////////////////////////
void ConfigWidget::UpdateVector3dMsg(google::protobuf::Message *_msg,
const ignition::math::Vector3d &_value)
{
const google::protobuf::Descriptor *valueDescriptor = _msg->GetDescriptor();
std::vector<double> values;
values.push_back(_value.X());
values.push_back(_value.Y());
values.push_back(_value.Z());
for (unsigned int i = 0; i < 3; ++i)
{
const google::protobuf::FieldDescriptor *valueField =
valueDescriptor->field(i);
_msg->GetReflection()->SetDouble(_msg, valueField, values[i]);
}
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateIntWidget(ConfigChildWidget *_widget, int _value)
{
if (_widget->widgets.size() == 1u)
{
qobject_cast<QSpinBox *>(_widget->widgets[0])->setValue(_value);
return true;
}
else
{
gzerr << "Error updating Int Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateUIntWidget(ConfigChildWidget *_widget,
unsigned int _value)
{
if (_widget->widgets.size() == 1u)
{
qobject_cast<QSpinBox *>(_widget->widgets[0])->setValue(_value);
return true;
}
else
{
gzerr << "Error updating UInt Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateDoubleWidget(ConfigChildWidget *_widget, double _value)
{
if (_widget->widgets.size() == 1u)
{
// Spin value
QDoubleSpinBox *spin =
qobject_cast<QDoubleSpinBox *>(_widget->widgets[0]);
spin->setValue(_value);
// Unit label
std::string jointType = this->EnumWidgetValue("type");
std::string unit = this->UnitFromKey(_widget->key, jointType);
qobject_cast<QLabel *>(
_widget->mapWidgetToUnit[spin])->setText(QString::fromStdString(unit));
return true;
}
else
{
gzerr << "Error updating Double Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateStringWidget(ConfigChildWidget *_widget,
const std::string &_value)
{
if (_widget->widgets.size() == 1u)
{
if (qobject_cast<QLineEdit *>(_widget->widgets[0]))
{
qobject_cast<QLineEdit *>(_widget->widgets[0])
->setText(tr(_value.c_str()));
return true;
}
else if (qobject_cast<QPlainTextEdit *>(_widget->widgets[0]))
{
qobject_cast<QPlainTextEdit *>(_widget->widgets[0])
->setPlainText(tr(_value.c_str()));
return true;
}
}
else
{
gzerr << "Error updating String Config Widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateBoolWidget(ConfigChildWidget *_widget, bool _value)
{
if (_widget->widgets.size() == 2u)
{
qobject_cast<QRadioButton *>(_widget->widgets[0])->setChecked(_value);
qobject_cast<QRadioButton *>(_widget->widgets[1])->setChecked(!_value);
return true;
}
else
{
gzerr << "Error updating Bool Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateVector3dWidget(ConfigChildWidget *_widget,
const ignition::math::Vector3d &_vec)
{
if (_widget->widgets.size() == 4u)
{
qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->setValue(_vec.X());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->setValue(_vec.Y());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->setValue(_vec.Z());
// Update preset
int preset = 0;
if (_vec == ignition::math::Vector3d::UnitX)
preset = 1;
else if (_vec == -ignition::math::Vector3d::UnitX)
preset = 2;
else if (_vec == ignition::math::Vector3d::UnitY)
preset = 3;
else if (_vec == -ignition::math::Vector3d::UnitY)
preset = 4;
else if (_vec == ignition::math::Vector3d::UnitZ)
preset = 5;
else if (_vec == -ignition::math::Vector3d::UnitZ)
preset = 6;
qobject_cast<QComboBox *>(_widget->widgets[3])->setCurrentIndex(preset);
return true;
}
else
{
gzerr << "Error updating Vector3 Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateColorWidget(ConfigChildWidget *_widget,
const common::Color &_color)
{
if (_widget->widgets.size() == 4u)
{
qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->setValue(_color.r);
qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->setValue(_color.g);
qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->setValue(_color.b);
qobject_cast<QDoubleSpinBox *>(_widget->widgets[3])->setValue(_color.a);
return true;
}
else
{
gzerr << "Error updating Color Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdatePoseWidget(ConfigChildWidget *_widget,
const ignition::math::Pose3d &_pose)
{
if (_widget->widgets.size() == 6u)
{
qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->setValue(
_pose.Pos().X());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->setValue(
_pose.Pos().Y());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->setValue(
_pose.Pos().Z());
ignition::math::Vector3d rot = _pose.Rot().Euler();
qobject_cast<QDoubleSpinBox *>(_widget->widgets[3])->setValue(rot.X());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[4])->setValue(rot.Y());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[5])->setValue(rot.Z());
return true;
}
else
{
gzerr << "Error updating Pose Config widget" << std::endl;
}
return false;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateGeometryWidget(ConfigChildWidget *_widget,
const std::string &_value, const ignition::math::Vector3d &_dimensions,
const std::string &_uri)
{
if (_widget->widgets.size() != 8u)
{
gzerr << "Error updating Geometry Config widget " << std::endl;
return false;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(_widget->widgets[0]);
int index = valueComboBox->findText(tr(_value.c_str()));
if (index < 0)
{
gzerr << "Error updating Geometry Config widget: '" << _value <<
"' not found" << std::endl;
return false;
}
qobject_cast<QComboBox *>(_widget->widgets[0])->setCurrentIndex(index);
bool isMesh = _value == "mesh";
if (_value == "box" || isMesh)
{
qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->setValue(
_dimensions.X());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->setValue(
_dimensions.Y());
qobject_cast<QDoubleSpinBox *>(_widget->widgets[3])->setValue(
_dimensions.Z());
}
else if (_value == "cylinder")
{
qobject_cast<QDoubleSpinBox *>(_widget->widgets[4])->setValue(
_dimensions.X()*0.5);
qobject_cast<QDoubleSpinBox *>(_widget->widgets[5])->setValue(
_dimensions.Z());
}
else if (_value == "sphere")
{
qobject_cast<QDoubleSpinBox *>(_widget->widgets[4])->setValue(
_dimensions.X()*0.5);
}
else if (_value == "polyline")
{
// do nothing
}
if (isMesh)
qobject_cast<QLineEdit *>(_widget->widgets[6])->setText(tr(_uri.c_str()));
return true;
}
/////////////////////////////////////////////////
bool ConfigWidget::UpdateEnumWidget(ConfigChildWidget *_widget,
const std::string &_value)
{
if (_widget->widgets.size() != 1u)
{
gzerr << "Error updating Enum Config widget" << std::endl;
return false;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(_widget->widgets[0]);
if (!valueComboBox)
{
gzerr << "Error updating Enum Config widget" << std::endl;
return false;
}
int index = valueComboBox->findText(tr(_value.c_str()));
if (index < 0)
{
gzerr << "Error updating Enum Config widget: '" << _value <<
"' not found" << std::endl;
return false;
}
qobject_cast<QComboBox *>(_widget->widgets[0])->setCurrentIndex(index);
return true;
}
/////////////////////////////////////////////////
int ConfigWidget::IntWidgetValue(ConfigChildWidget *_widget) const
{
int value = 0;
if (_widget->widgets.size() == 1u)
{
value = qobject_cast<QSpinBox *>(_widget->widgets[0])->value();
}
else
{
gzerr << "Error getting value from Int Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
unsigned int ConfigWidget::UIntWidgetValue(ConfigChildWidget *_widget) const
{
unsigned int value = 0;
if (_widget->widgets.size() == 1u)
{
value = qobject_cast<QSpinBox *>(_widget->widgets[0])->value();
}
else
{
gzerr << "Error getting value from UInt Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
double ConfigWidget::DoubleWidgetValue(ConfigChildWidget *_widget) const
{
double value = 0.0;
if (_widget->widgets.size() == 1u)
{
value = qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->value();
}
else
{
gzerr << "Error getting value from Double Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
std::string ConfigWidget::StringWidgetValue(ConfigChildWidget *_widget) const
{
std::string value;
if (_widget->widgets.size() == 1u)
{
if (qobject_cast<QLineEdit *>(_widget->widgets[0]))
{
value =
qobject_cast<QLineEdit *>(_widget->widgets[0])->text().toStdString();
}
else if (qobject_cast<QPlainTextEdit *>(_widget->widgets[0]))
{
value = qobject_cast<QPlainTextEdit *>(_widget->widgets[0])
->toPlainText().toStdString();
}
}
else
{
gzerr << "Error getting value from String Config Widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
bool ConfigWidget::BoolWidgetValue(ConfigChildWidget *_widget) const
{
bool value = false;
if (_widget->widgets.size() == 2u)
{
value = qobject_cast<QRadioButton *>(_widget->widgets[0])->isChecked();
}
else
{
gzerr << "Error getting value from Bool Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
ignition::math::Vector3d ConfigWidget::Vector3dWidgetValue(
ConfigChildWidget *_widget) const
{
ignition::math::Vector3d value;
if (_widget->widgets.size() == 4u)
{
value.X(qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->value());
value.Y(qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->value());
value.Z(qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->value());
}
else
{
gzerr << "Error getting value from Vector3 Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
common::Color ConfigWidget::ColorWidgetValue(ConfigChildWidget *_widget)
const
{
common::Color value;
if (_widget->widgets.size() == 4u)
{
value.r = qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->value();
value.g = qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->value();
value.b = qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->value();
value.a = qobject_cast<QDoubleSpinBox *>(_widget->widgets[3])->value();
}
else
{
gzerr << "Error getting value from Color Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
ignition::math::Pose3d ConfigWidget::PoseWidgetValue(ConfigChildWidget *_widget)
const
{
ignition::math::Pose3d value;
if (_widget->widgets.size() == 6u)
{
value.Pos().X(qobject_cast<QDoubleSpinBox *>(_widget->widgets[0])->value());
value.Pos().Y(qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->value());
value.Pos().Z(qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->value());
ignition::math::Vector3d rot;
rot.X(qobject_cast<QDoubleSpinBox *>(_widget->widgets[3])->value());
rot.Y(qobject_cast<QDoubleSpinBox *>(_widget->widgets[4])->value());
rot.Z(qobject_cast<QDoubleSpinBox *>(_widget->widgets[5])->value());
value.Rot().Euler(rot);
}
else
{
gzerr << "Error getting value from Pose Config widget" << std::endl;
}
return value;
}
/////////////////////////////////////////////////
std::string ConfigWidget::GeometryWidgetValue(ConfigChildWidget *_widget,
ignition::math::Vector3d &_dimensions, std::string &_uri) const
{
std::string value;
if (_widget->widgets.size() != 8u)
{
gzerr << "Error getting value from Geometry Config widget " << std::endl;
return value;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(_widget->widgets[0]);
value = valueComboBox->currentText().toStdString();
bool isMesh = value == "mesh";
if (value == "box" || isMesh)
{
_dimensions.X(qobject_cast<QDoubleSpinBox *>(_widget->widgets[1])->value());
_dimensions.Y(qobject_cast<QDoubleSpinBox *>(_widget->widgets[2])->value());
_dimensions.Z(qobject_cast<QDoubleSpinBox *>(_widget->widgets[3])->value());
}
else if (value == "cylinder")
{
_dimensions.X(
qobject_cast<QDoubleSpinBox *>(_widget->widgets[4])->value()*2.0);
_dimensions.Y(_dimensions.X());
_dimensions.Z(qobject_cast<QDoubleSpinBox *>(_widget->widgets[5])->value());
}
else if (value == "sphere")
{
_dimensions.X(
qobject_cast<QDoubleSpinBox *>(_widget->widgets[4])->value()*2.0);
_dimensions.Y(_dimensions.X());
_dimensions.Z(_dimensions.X());
}
else if (value == "polyline")
{
// do nothing
}
else
{
gzerr << "Error getting geometry dimensions for type: '" << value << "'"
<< std::endl;
}
if (isMesh)
_uri = qobject_cast<QLineEdit *>(_widget->widgets[6])->text().toStdString();
return value;
}
/////////////////////////////////////////////////
std::string ConfigWidget::EnumWidgetValue(ConfigChildWidget *_widget) const
{
std::string value;
if (_widget->widgets.size() != 1u)
{
gzerr << "Error getting value from Enum Config widget " << std::endl;
return value;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(_widget->widgets[0]);
value = valueComboBox->currentText().toStdString();
return value;
}
/////////////////////////////////////////////////
void ConfigWidget::OnItemSelection(QTreeWidgetItem *_item,
const int /*_column*/)
{
if (_item && _item->childCount() > 0)
_item->setExpanded(!_item->isExpanded());
}
/////////////////////////////////////////////////
void ConfigWidget::OnUIntValueChanged()
{
QSpinBox *spin =
qobject_cast<QSpinBox *>(QObject::sender());
if (!spin)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(spin->parent());
if (!widget)
return;
emit UIntValueChanged(widget->scopedName.c_str(),
this->UIntWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnIntValueChanged()
{
QSpinBox *spin =
qobject_cast<QSpinBox *>(QObject::sender());
if (!spin)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(spin->parent());
if (!widget)
return;
emit IntValueChanged(widget->scopedName.c_str(),
this->IntWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnDoubleValueChanged()
{
QDoubleSpinBox *spin =
qobject_cast<QDoubleSpinBox *>(QObject::sender());
if (!spin)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(spin->parent());
if (!widget)
return;
emit DoubleValueChanged(widget->scopedName.c_str(),
this->DoubleWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnBoolValueChanged()
{
QRadioButton *radio =
qobject_cast<QRadioButton *>(QObject::sender());
if (!radio)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(radio->parent());
if (!widget)
return;
emit BoolValueChanged(widget->scopedName.c_str(),
this->BoolWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnStringValueChanged()
{
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(QObject::sender());
QPlainTextEdit *plainTextEdit =
qobject_cast<QPlainTextEdit *>(QObject::sender());
QWidget *valueEdit;
if (!lineEdit && !plainTextEdit)
return;
else if (lineEdit)
valueEdit = lineEdit;
else
valueEdit = plainTextEdit;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(valueEdit->parent());
if (!widget)
return;
emit StringValueChanged(widget->scopedName.c_str(),
this->StringWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnVector3dValueChanged()
{
QDoubleSpinBox *spin =
qobject_cast<QDoubleSpinBox *>(QObject::sender());
if (!spin)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(spin->parent());
if (!widget)
return;
auto value = this->Vector3dWidgetValue(widget);
// Update preset
this->UpdateVector3dWidget(widget, value);
// Signal
emit Vector3dValueChanged(widget->scopedName.c_str(), value);
}
/////////////////////////////////////////////////
void ConfigWidget::OnVector3dPresetChanged(const int _index)
{
auto combo = qobject_cast<QComboBox *>(QObject::sender());
if (!combo)
return;
auto widget = qobject_cast<ConfigChildWidget *>(combo->parent());
if (!widget)
return;
// Update spins
ignition::math::Vector3d vec;
if (_index == 1)
vec = ignition::math::Vector3d::UnitX;
else if (_index == 2)
vec = -ignition::math::Vector3d::UnitX;
else if (_index == 3)
vec = ignition::math::Vector3d::UnitY;
else if (_index == 4)
vec = -ignition::math::Vector3d::UnitY;
else if (_index == 5)
vec = ignition::math::Vector3d::UnitZ;
else if (_index == 6)
vec = -ignition::math::Vector3d::UnitZ;
else
return;
this->UpdateVector3dWidget(widget, vec);
// Signal
emit Vector3dValueChanged(widget->scopedName.c_str(), vec);
}
/////////////////////////////////////////////////
void ConfigWidget::OnColorValueChanged()
{
QDoubleSpinBox *spin =
qobject_cast<QDoubleSpinBox *>(QObject::sender());
if (!spin)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(spin->parent());
if (!widget)
return;
emit ColorValueChanged(widget->scopedName.c_str(),
this->ColorWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnPoseValueChanged()
{
QDoubleSpinBox *spin =
qobject_cast<QDoubleSpinBox *>(QObject::sender());
if (!spin)
return;
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(spin->parent());
if (!widget)
return;
emit PoseValueChanged(widget->scopedName.c_str(),
this->PoseWidgetValue(widget));
}
/////////////////////////////////////////////////
void ConfigWidget::OnGeometryValueChanged()
{
QWidget *senderWidget = qobject_cast<QWidget *>(QObject::sender());
if (!senderWidget)
return;
ConfigChildWidget *widget;
while (senderWidget->parent() != NULL)
{
senderWidget = qobject_cast<QWidget *>(senderWidget->parent());
widget = qobject_cast<ConfigChildWidget *>(senderWidget);
if (widget)
break;
}
if (!widget)
return;
ignition::math::Vector3d dimensions;
std::string uri;
std::string value = this->GeometryWidgetValue(widget, dimensions, uri);
emit GeometryValueChanged(widget->scopedName.c_str(), value, dimensions,
uri);
}
/////////////////////////////////////////////////
void ConfigWidget::OnGeometryValueChanged(const int /*_value*/)
{
QComboBox *combo =
qobject_cast<QComboBox *>(QObject::sender());
if (!combo)
return;
GeometryConfigWidget *widget =
qobject_cast<GeometryConfigWidget *>(combo->parent());
if (!widget)
return;
ignition::math::Vector3d dimensions;
std::string uri;
std::string value = this->GeometryWidgetValue(widget, dimensions, uri);
emit GeometryValueChanged(widget->scopedName.c_str(), value, dimensions, uri);
}
/////////////////////////////////////////////////
void ConfigWidget::OnEnumValueChanged(const QString &_value)
{
ConfigChildWidget *widget =
qobject_cast<ConfigChildWidget *>(QObject::sender());
if (!widget)
return;
emit EnumValueChanged(widget->scopedName.c_str(), _value);
}
/////////////////////////////////////////////////
bool ConfigWidget::AddConfigChildWidget(const std::string &_name,
ConfigChildWidget *_child)
{
if (_name.empty() || _child == NULL)
{
gzerr << "Given name or child is invalid. Not adding child widget."
<< std::endl;
return false;
}
if (this->dataPtr->configWidgets.find(_name) !=
this->dataPtr->configWidgets.end())
{
gzerr << "This config widget already has a child with that name. " <<
"Names must be unique. Not adding child." << std::endl;
return false;
}
_child->scopedName = _name;
this->dataPtr->configWidgets[_name] = _child;
return true;
}
/////////////////////////////////////////////////
unsigned int ConfigWidget::ConfigChildWidgetCount() const
{
return this->dataPtr->configWidgets.size();
}
/////////////////////////////////////////////////
bool ConfigWidget::eventFilter(QObject *_obj, QEvent *_event)
{
QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(_obj);
QComboBox *comboBox = qobject_cast<QComboBox *>(_obj);
if (spinBox || comboBox)
{
QWidget *widget = qobject_cast<QWidget *>(_obj);
if (_event->type() == QEvent::Wheel)
{
if (widget->focusPolicy() == Qt::WheelFocus)
{
_event->accept();
return false;
}
else
{
_event->ignore();
return true;
}
}
else if (_event->type() == QEvent::FocusIn)
{
widget->setFocusPolicy(Qt::WheelFocus);
}
else if (_event->type() == QEvent::FocusOut)
{
widget->setFocusPolicy(Qt::StrongFocus);
}
}
return QObject::eventFilter(_obj, _event);
}
/////////////////////////////////////////////////
void GroupWidget::Toggle(bool _checked)
{
if (!this->childWidget)
return;
this->childWidget->setVisible(_checked);
}
/////////////////////////////////////////////////
void GeometryConfigWidget::GeometryChanged(const QString _text)
{
QWidget *widget= qobject_cast<QWidget *>(QObject::sender());
if (widget)
{
std::string textStr = _text.toStdString();
bool isMesh = (textStr == "mesh");
if (textStr == "box" || isMesh)
{
this->geomDimensionWidget->show();
this->geomDimensionWidget->setCurrentIndex(0);
}
else if (textStr == "cylinder")
{
this->geomDimensionWidget->show();
this->geomDimensionWidget->setCurrentIndex(1);
this->geomLengthSpinBox->show();
this->geomLengthLabel->show();
this->geomLengthUnitLabel->show();
}
else if (textStr == "sphere")
{
this->geomDimensionWidget->show();
this->geomDimensionWidget->setCurrentIndex(1);
this->geomLengthSpinBox->hide();
this->geomLengthLabel->hide();
this->geomLengthUnitLabel->hide();
}
else if (textStr == "polyline")
{
this->geomDimensionWidget->hide();
}
this->geomFilenameLabel->setVisible(isMesh);
this->geomFilenameLineEdit->setVisible(isMesh);
this->geomFilenameButton->setVisible(isMesh);
}
}
/////////////////////////////////////////////////
void GeometryConfigWidget::OnSelectFile()
{
QWidget *widget= qobject_cast<QWidget *>(QObject::sender());
if (widget)
{
QFileDialog fd(this, tr("Select mesh file"), QDir::homePath(),
tr("Mesh files (*.dae *.stl)"));
fd.setFilter(QDir::AllDirs | QDir::Hidden);
fd.setFileMode(QFileDialog::ExistingFile);
fd.setWindowFlags(Qt::Window | Qt::WindowCloseButtonHint |
Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint);
if (fd.exec())
{
if (!fd.selectedFiles().isEmpty())
{
QString file = fd.selectedFiles().at(0);
if (!file.isEmpty())
{
dynamic_cast<QLineEdit *>(this->geomFilenameLineEdit)->setText(file);
}
}
}
}
}
/////////////////////////////////////////////////
void EnumConfigWidget::EnumChanged(const QString &_value)
{
emit EnumValueChanged(_value);
}
/////////////////////////////////////////////////
bool ConfigWidget::ClearEnumWidget(const std::string &_name)
{
// Find widget
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter == this->dataPtr->configWidgets.end())
return false;
EnumConfigWidget *enumWidget = dynamic_cast<EnumConfigWidget *>(iter->second);
if (enumWidget->widgets.size() != 1u)
{
gzerr << "Enum config widget has wrong number of widgets." << std::endl;
return false;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(enumWidget->widgets[0]);
if (!valueComboBox)
{
gzerr << "Enum config widget doesn't have a QComboBox." << std::endl;
return false;
}
// Clear
valueComboBox->blockSignals(true);
valueComboBox->clear();
valueComboBox->blockSignals(false);
return true;
}
/////////////////////////////////////////////////
bool ConfigWidget::AddItemEnumWidget(const std::string &_name,
const std::string &_itemText)
{
// Find widget
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter == this->dataPtr->configWidgets.end())
return false;
EnumConfigWidget *enumWidget = dynamic_cast<EnumConfigWidget *>(iter->second);
if (enumWidget->widgets.size() != 1u)
{
gzerr << "Enum config widget has wrong number of widgets." << std::endl;
return false;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(enumWidget->widgets[0]);
if (!valueComboBox)
{
gzerr << "Enum config widget doesn't have a QComboBox." << std::endl;
return false;
}
// Add item
valueComboBox->blockSignals(true);
valueComboBox->addItem(QString::fromStdString(_itemText));
valueComboBox->blockSignals(false);
return true;
}
/////////////////////////////////////////////////
bool ConfigWidget::RemoveItemEnumWidget(const std::string &_name,
const std::string &_itemText)
{
// Find widget
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter == this->dataPtr->configWidgets.end())
return false;
EnumConfigWidget *enumWidget = dynamic_cast<EnumConfigWidget *>(iter->second);
if (enumWidget->widgets.size() != 1u)
{
gzerr << "Enum config widget has wrong number of widgets." << std::endl;
return false;
}
QComboBox *valueComboBox = qobject_cast<QComboBox *>(enumWidget->widgets[0]);
if (!valueComboBox)
{
gzerr << "Enum config widget doesn't have a QComboBox." << std::endl;
return false;
}
// Remove item if exists, otherwise return false
int index = valueComboBox->findText(QString::fromStdString(
_itemText));
if (index < 0)
return false;
valueComboBox->blockSignals(true);
valueComboBox->removeItem(index);
valueComboBox->blockSignals(false);
return true;
}
/////////////////////////////////////////////////
void ConfigWidget::InsertLayout(QLayout *_layout, int _pos)
{
QGroupBox *box = qobject_cast<QGroupBox *>(
this->layout()->itemAt(0)->widget());
if (!box)
return;
QVBoxLayout *boxLayout = qobject_cast<QVBoxLayout *>(box->layout());
if (!boxLayout)
return;
boxLayout->insertLayout(_pos, _layout);
}
/////////////////////////////////////////////////
ConfigChildWidget *ConfigWidget::ConfigChildWidgetByName(
const std::string &_name) const
{
auto iter = this->dataPtr->configWidgets.find(_name);
if (iter != this->dataPtr->configWidgets.end())
return iter->second;
else
return NULL;
}
/////////////////////////////////////////////////
QString ConfigWidget::StyleSheet(const std::string &_type, const int _level)
{
if (_type == "normal")
{
return "QWidget\
{\
background-color: " + ConfigWidget::bgColors[_level] + ";\
color: #4c4c4c;\
}\
QLabel\
{\
color: #d0d0d0;\
}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox\
{\
background-color: " + ConfigWidget::widgetColors[_level] +
"}";
}
else if (_type == "warning")
{
return "QWidget\
{\
background-color: " + ConfigWidget::bgColors[_level] + ";\
color: " + ConfigWidget::redColor + ";\
}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox\
{\
background-color: " + ConfigWidget::widgetColors[_level] +
"}";
}
else if (_type == "active")
{
return "QWidget\
{\
background-color: " + ConfigWidget::bgColors[_level] + ";\
color: " + ConfigWidget::greenColor + ";\
}\
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox\
{\
background-color: " + ConfigWidget::widgetColors[_level] +
"}";
}
gzwarn << "Requested unknown style sheet type [" << _type << "]" << std::endl;
return "";
}