Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "qt_paramedit/xmlRpcTreeItem.h"
00030 #include <QDateTime>
00031
00032 #include <boost/foreach.hpp>
00033 #define forEach BOOST_FOREACH
00034
00035 XmlRpcTreeItem::XmlRpcTreeItem(XmlRpc::XmlRpcValue* data, XmlRpcTreeItem* parent, const std::string & path,
00036 ros::NodeHandle* nh)
00037 : _data(data), _parent(parent), _path(path), _nh(nh)
00038 {
00039 ROS_ASSERT(_nh != NULL);
00040
00041 createChildren();
00042 }
00043
00044 XmlRpcTreeItem::~XmlRpcTreeItem()
00045 {
00046 forEach(XmlRpcTreeItem* child, _children)
00047 delete child;
00048 _children.clear();
00049 }
00050
00055 unsigned int XmlRpcTreeItem::childCount() const
00056 {
00057 if(_children.size() > 0)
00058 return _children.size();
00059
00060 return 0;
00061 }
00062
00063 int XmlRpcTreeItem::childIndexOf(const XmlRpcTreeItem* child) const
00064 {
00065 int index = -1;
00066 for(unsigned int i = 0; i < _children.size(); i++) {
00067 if(child == _children[i]) {
00068 index = i;
00069 break;
00070 }
00071 }
00072 return index;
00073 }
00074
00075 int XmlRpcTreeItem::row() const
00076 {
00077 if(_parent) {
00078 return _parent->childIndexOf(this);
00079 }
00080
00081
00082 return 0;
00083 }
00084
00085 QVariant XmlRpcTreeItem::xmlToVariant(XmlRpc::XmlRpcValue & val) const
00086 {
00087 switch(val.getType()) {
00088 case XmlRpc::XmlRpcValue::TypeBoolean:
00089 return QVariant( (bool)val );
00090 break;
00091 case XmlRpc::XmlRpcValue::TypeInt:
00092 return QVariant( (int)val );
00093 break;
00094 case XmlRpc::XmlRpcValue::TypeDouble:
00095 return QVariant( (double)val );
00096 break;
00097 case XmlRpc::XmlRpcValue::TypeString:
00098 return QVariant( ((std::string)val).c_str() );
00099 break;
00100 case XmlRpc::XmlRpcValue::TypeDateTime:
00101 {
00102 ROS_WARN_THROTTLE(1.0, "Accessing TypeDateTime is untested.");
00103 struct tm time = (struct tm)val;
00104 int ms = 0;
00105 if(time.tm_sec > 59)
00106 ms = 999;
00107
00108 return QVariant( QDateTime(
00109
00110
00111
00112
00113
00114 QDate(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday),
00115
00116
00117
00118
00119
00120 QTime(time.tm_hour, time.tm_min, time.tm_sec, ms)));
00121 break;
00122 }
00123 case XmlRpc::XmlRpcValue::TypeBase64:
00124 {
00125 ROS_WARN_THROTTLE(1.0, "Accessing TypeBase64 is untested.");
00126 XmlRpc::XmlRpcValue::BinaryData & bd = (XmlRpc::XmlRpcValue::BinaryData&)val;
00127 QByteArray ba;
00128 for(std::vector<char>::iterator it = bd.begin(); it != bd.end(); it++)
00129 ba.append(*it);
00130 return QVariant(ba);
00131 break;
00132 }
00133 default:
00134 return QVariant();
00135 }
00136
00137 return QVariant();
00138 }
00139
00140 QVariant XmlRpcTreeItem::data(int row, int column) const
00141 {
00142
00143
00144 if(column > 1)
00145 return QVariant();
00146
00147
00148 if(_data->getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00149 int count = 0;
00150 for(XmlRpc::XmlRpcValue::iterator it = _data->begin(); it != _data->end(); it++) {
00151 if(count == row) {
00152 if(column == 0) {
00153 return it->first.c_str();
00154 }
00155 if(column == 1) {
00156 XmlRpc::XmlRpcValue & val = it->second;
00157 return xmlToVariant(val);
00158 }
00159 }
00160 count++;
00161 }
00162 } else if(_data->getType() == XmlRpc::XmlRpcValue::TypeArray) {
00163 if(column == 0) {
00164 return QString("[%1]").arg(row);
00165 } else {
00166 XmlRpc::XmlRpcValue & val = (*_data)[row];
00167 return xmlToVariant(val);
00168 }
00169 }
00170
00171
00172 return QVariant();
00173 }
00174
00175 bool XmlRpcTreeItem::isBool(int row, int column) const
00176 {
00177
00178
00179 if(column != 1)
00180 return false;
00181
00182
00183 if(_data->getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00184 int count = 0;
00185 for(XmlRpc::XmlRpcValue::iterator it = _data->begin(); it != _data->end(); it++) {
00186 if(count == row) {
00187 XmlRpc::XmlRpcValue & val = it->second;
00188 if(val.getType() == XmlRpc::XmlRpcValue::TypeBoolean)
00189 return true;
00190 else
00191 return false;
00192 }
00193 count++;
00194 }
00195 } else if(_data->getType() == XmlRpc::XmlRpcValue::TypeArray) {
00196 XmlRpc::XmlRpcValue & val = (*_data)[row];
00197 if(val.getType() == XmlRpc::XmlRpcValue::TypeBoolean)
00198 return true;
00199 else
00200 return false;
00201 }
00202
00203
00204 return false;
00205 }
00206
00207 bool XmlRpcTreeItem::setData(QVariant val)
00208 {
00209 XmlRpc::XmlRpcValue::Type type = _data->getType();
00210 if(type == XmlRpc::XmlRpcValue::TypeStruct || type == XmlRpc::XmlRpcValue::TypeArray
00211 || type == XmlRpc::XmlRpcValue::TypeInvalid) {
00212 return false;
00213 }
00214
00215 bool setXmlOK = false;
00216 switch(type) {
00217 case XmlRpc::XmlRpcValue::TypeBoolean:
00218 if(!val.canConvert(QVariant::Bool)) {
00219 ROS_WARN("XmlRpcValue TypeBoolean -- setData cannot convert from QVariant type %d.", val.type());
00220 break;
00221 }
00222 ROS_DEBUG("Setting bool param.");
00223 (bool&)(*_data) = val.toBool();
00224 setXmlOK = true;
00225 break;
00226 case XmlRpc::XmlRpcValue::TypeInt:
00227 {
00228 if(!val.canConvert(QVariant::Int)) {
00229 ROS_WARN("XmlRpcValue TypeInt -- setData cannot convert from QVariant type %d.", val.type());
00230 break;
00231 }
00232 bool ok = false;
00233 int iVal = val.toInt(&ok);
00234 if(ok) {
00235 ROS_DEBUG("Setting int param.");
00236 (int&)(*_data) = iVal;
00237 setXmlOK = true;
00238 }
00239 break;
00240 }
00241 case XmlRpc::XmlRpcValue::TypeDouble:
00242 {
00243 if(!val.canConvert(QVariant::Double)) {
00244 ROS_WARN("XmlRpcValue TypeDouble -- setData cannot convert from QVariant type %d.", val.type());
00245 break;
00246 }
00247
00248
00249 bool ok = false;
00250 double dVal = val.toDouble(&ok);
00251 if(ok) {
00252 ROS_DEBUG("Setting double param.");
00253 (double&)(*_data) = dVal;
00254 setXmlOK = true;
00255 }
00256 break;
00257 }
00258 case XmlRpc::XmlRpcValue::TypeString:
00259 if(!val.canConvert(QVariant::String)) {
00260 ROS_WARN("XmlRpcValue TypeString -- setData cannot convert from QVariant type %d.", val.type());
00261 break;
00262 }
00263 ROS_DEBUG("Setting string param.");
00264 (std::string&)(*_data) = qPrintable(val.toString());
00265 setXmlOK = true;
00266 break;
00267 case XmlRpc::XmlRpcValue::TypeDateTime:
00268 {
00269 ROS_WARN_THROTTLE(1.0, "Accessing TypeDateTime is untested.");
00270 if(!val.canConvert(QVariant::DateTime)) {
00271 ROS_WARN("XmlRpcValue TypeDateTime -- setData cannot convert from QVariant type %d.", val.type());
00272 break;
00273 }
00274 QDateTime dt = val.toDateTime();
00275 if(dt.isValid()) {
00276 ROS_DEBUG("Setting datetime param.");
00277 struct tm time;
00278 time.tm_year = dt.date().year() - 1900;
00279 time.tm_mon = dt.date().month() - 1;
00280 time.tm_mday = dt.date().day();
00281 time.tm_hour = dt.time().hour();
00282 time.tm_min = dt.time().minute();
00283 time.tm_sec = dt.time().second();
00284 time.tm_wday = dt.date().dayOfWeek() - 1;
00285 time.tm_yday = dt.date().dayOfYear() - 1;
00286 time.tm_isdst = -1;
00287 time.tm_zone = "";
00288 time.tm_gmtoff = 0;
00289
00290 (struct tm &)(*_data) = time;
00291 setXmlOK = true;
00292 }
00293 break;
00294 }
00295 case XmlRpc::XmlRpcValue::TypeBase64:
00296 {
00297 ROS_WARN_THROTTLE(1.0, "Accessing TypeBase64 is untested.");
00298 if(!val.canConvert(QVariant::ByteArray)) {
00299 ROS_WARN("XmlRpcValue TypeBase64 -- setData cannot convert from QVariant type %d.", val.type());
00300 break;
00301 }
00302 QByteArray ba = val.toByteArray();
00303 XmlRpc::XmlRpcValue::BinaryData bd;
00304 for(int i = 0; i < ba.size(); i++) {
00305 bd.push_back(ba.at(i));
00306 }
00307 ROS_DEBUG("Setting base64 param.");
00308 (XmlRpc::XmlRpcValue::BinaryData &)(*_data) = bd;
00309 break;
00310 }
00311 default:
00312 return false;
00313 }
00314 if(setXmlOK) {
00315 if(!_path.empty()) {
00316 ROS_DEBUG("Setting param type %d on server path %s.", _data->getType(), _path.c_str());
00317 _nh->setParam(_path, *_data);
00318 } else {
00319 _parent->setParam();
00320 }
00321 }
00322
00323 return true;
00324 }
00325
00326 void XmlRpcTreeItem::setParam()
00327 {
00328 ROS_ASSERT(_data->getType() == XmlRpc::XmlRpcValue::TypeArray);
00329
00330 ROS_DEBUG("Setting param type %d on server path %s.", _data->getType(), _path.c_str());
00331 if(!_path.empty())
00332 _nh->setParam(_path, *_data);
00333 }
00334
00335 void XmlRpcTreeItem::createChildren()
00336 {
00337
00338
00339 if(_data->getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00340 for(XmlRpc::XmlRpcValue::iterator it = _data->begin(); it != _data->end(); it++) {
00341 addChild(it->first, &it->second);
00342 }
00343 } else if(_data->getType() == XmlRpc::XmlRpcValue::TypeArray) {
00344 for(int i = 0; i < _data->size(); i++) {
00345 addChild("", & ((*_data)[i]));
00346 }
00347 }
00348 }
00349
00350 void XmlRpcTreeItem::addChild(const std::string & name, XmlRpc::XmlRpcValue* childData)
00351 {
00352 std::string path = ros::names::append(this->_path, name);
00353 if(name.empty())
00354 path = name;
00355 XmlRpcTreeItem* child = new XmlRpcTreeItem(childData, this, path, _nh);
00356 _children.push_back(child);
00357 }
00358