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