32 #include <boost/filesystem.hpp> 40 #include <QTextBrowser> 41 #include <QVBoxLayout> 42 #include <QDialogButtonBox> 43 #include <QPushButton> 47 #include <QHeaderView> 80 bool isSubtopic(
const std::string& base,
const std::string& topic)
94 std::string query = topic;
120 QList<PluginGroup>* groups,
121 QList<ros::master::TopicInfo>* unvisualizable)
126 ros::master::V_TopicInfo::iterator topic_it;
128 for (topic_it = all_topics.begin(); topic_it != all_topics.end(); ++topic_it)
130 QString topic = QString::fromStdString(topic_it->name);
131 QString
datatype = QString::fromStdString(topic_it->datatype);
133 if (datatype_plugins.contains(datatype))
135 if (groups->empty() || !
isSubtopic(groups->back().base_topic.toStdString(), topic.toStdString()))
143 QString topic_suffix(
"raw");
147 topic_suffix = topic.right(topic.size() - group.
base_topic.size() - 1);
150 const QList<QString>& plugin_names = datatype_plugins.values(datatype);
151 for (
int i = 0; i < plugin_names.size(); ++i)
153 const QString& name = plugin_names[i];
161 unvisualizable->append(*topic_it);
169 const QStringList& disallowed_display_names,
170 const QStringList& disallowed_class_lookup_names,
171 QString* lookup_name_output,
172 QString* display_name_output,
173 QString* topic_output,
174 QString* datatype_output,
178 , disallowed_display_names_(disallowed_display_names)
179 , disallowed_class_lookup_names_(disallowed_class_lookup_names)
180 , lookup_name_output_(lookup_name_output)
181 , display_name_output_(display_name_output)
182 , topic_output_(topic_output)
183 , datatype_output_(datatype_output)
188 QGroupBox* type_box =
new QGroupBox(
"Create visualization");
190 QLabel* description_label =
new QLabel(
"Description:");
199 topic_widget->
fill(factory);
205 QVBoxLayout* type_layout =
new QVBoxLayout;
207 type_layout->addWidget(description_label);
210 type_box->setLayout(type_layout);
213 QGroupBox* name_box =
nullptr;
216 name_box =
new QGroupBox(
"Display Name");
218 QVBoxLayout* name_layout =
new QVBoxLayout;
220 name_box->setLayout(name_layout);
224 button_box_ =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
226 QVBoxLayout* main_layout =
new QVBoxLayout;
227 main_layout->addWidget(type_box);
230 main_layout->addWidget(name_box);
233 setLayout(main_layout);
236 connect(display_tree, SIGNAL(itemChanged(
SelectionData*)),
this,
238 connect(display_tree, SIGNAL(itemActivated(QTreeWidgetItem*,
int)),
this, SLOT(
accept()));
241 connect(topic_widget, SIGNAL(itemActivated(QTreeWidgetItem*,
int)),
this, SLOT(
accept()));
244 connect(
button_box_, SIGNAL(rejected()),
this, SLOT(reject()));
257 return (QSize(500, 660));
294 QString html =
"<html><body>" + data->
whats_this +
"</body></html>";
319 if (display_name.size() == 0)
321 setError(
"Enter a name for the display.");
326 setError(
"Name in use. Display names must be unique.");
336 button_box_->button(QDialogButtonBox::Ok)->setToolTip(error_text);
359 setHeaderHidden(
true);
361 connect(
this, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
this,
362 SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
369 if (curr->parent() !=
nullptr)
373 sd.
lookup_name = curr->data(0, Qt::UserRole).toString();
376 Q_EMIT itemChanged(&sd);
381 QIcon default_package_icon =
loadPixmap(
"package://rviz/icons/default_package_icon.png");
387 std::map<QString, QTreeWidgetItem*> package_items;
389 for (
int i = 0; i < classes.size(); i++)
391 QString lookup_name = classes[i];
392 QString
package = factory->getClassPackage(lookup_name);
396 QTreeWidgetItem* package_item;
398 std::map<QString, QTreeWidgetItem*>::iterator mi;
399 mi = package_items.find(
package);
400 if (mi == package_items.end())
402 package_item =
new QTreeWidgetItem(
this);
403 package_item->setText(0,
package);
404 package_item->setIcon(0, default_package_icon);
406 package_item->setExpanded(
true);
407 package_items[
package] = package_item;
411 package_item = (*mi).second;
413 QTreeWidgetItem* class_item =
new QTreeWidgetItem(package_item);
415 class_item->setIcon(0, factory->
getIcon(lookup_name));
417 class_item->setText(0, name);
418 class_item->setWhatsThis(0, description);
420 class_item->setData(0, Qt::UserRole, lookup_name);
426 tree_ =
new QTreeWidget;
427 tree_->setHeaderHidden(
true);
428 tree_->setColumnCount(2);
430 tree_->header()->setStretchLastSection(
false);
431 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) 432 tree_->header()->setResizeMode(0, QHeaderView::Stretch);
434 tree_->header()->setSectionResizeMode(0, QHeaderView::Stretch);
437 enable_hidden_box_ =
new QCheckBox(
"Show unvisualizable topics");
438 enable_hidden_box_->setCheckState(Qt::Unchecked);
440 QVBoxLayout* layout =
new QVBoxLayout;
441 layout->setContentsMargins(QMargins(0, 0, 0, 0));
443 layout->addWidget(tree_);
444 layout->addWidget(enable_hidden_box_);
446 connect(tree_, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
this,
447 SLOT(onCurrentItemChanged(QTreeWidgetItem*)));
449 connect(tree_, SIGNAL(itemActivated(QTreeWidgetItem*,
int)),
this,
450 SIGNAL(itemActivated(QTreeWidgetItem*,
int)));
453 connect(enable_hidden_box_, SIGNAL(stateChanged(
int)),
this, SLOT(stateChanged(
int)));
462 if (curr->data(1, Qt::UserRole).isValid())
464 QTreeWidgetItem* parent = curr->parent();
467 sd.
topic = parent->data(0, Qt::UserRole).toString();
468 sd.
lookup_name = curr->data(0, Qt::UserRole).toString();
471 QComboBox* combo = qobject_cast<QComboBox*>(tree_->itemWidget(curr, 1));
472 if (combo !=
nullptr)
474 QString combo_text = combo->currentText();
475 if (combo_text !=
"raw")
477 sd.
topic +=
"/" + combo_text;
479 sd.
datatype = combo->itemData(combo->currentIndex()).toString();
483 sd.
datatype = curr->data(1, Qt::UserRole).toString();
486 Q_EMIT itemChanged(&sd);
491 tree_->setCurrentItem(curr);
496 bool hide_disabled = state == Qt::Unchecked;
497 QTreeWidgetItemIterator it(tree_, QTreeWidgetItemIterator::Disabled);
500 QTreeWidgetItem* item = *it;
501 item->setHidden(hide_disabled);
507 findPlugins(factory);
509 QList<PluginGroup> groups;
510 QList<ros::master::TopicInfo> unvisualizable;
514 QList<PluginGroup>::const_iterator pg_it;
515 for (pg_it = groups.begin(); pg_it < groups.end(); ++pg_it)
519 QTreeWidgetItem* item = insertItem(pg.
base_topic,
false);
520 item->setData(0, Qt::UserRole, pg.
base_topic);
522 QMap<QString, PluginGroup::Info>::const_iterator it;
525 const QString plugin_name = it.key();
527 QTreeWidgetItem* row =
new QTreeWidgetItem(item);
530 row->setIcon(0, factory->
getIcon(plugin_name));
532 row->setData(0, Qt::UserRole, plugin_name);
533 row->setData(1, Qt::UserRole, info.
datatypes[0]);
538 connect(box, SIGNAL(itemClicked(QTreeWidgetItem*,
int)),
this,
539 SLOT(onComboBoxClicked(QTreeWidgetItem*)));
544 tree_->setItemWidget(row, 1, box);
545 tree_->setColumnWidth(1, std::max(tree_->columnWidth(1), box->width()));
551 for (
int i = 0; i < unvisualizable.size(); ++i)
554 insertItem(QString::fromStdString(ti.
name),
true);
558 stateChanged(enable_hidden_box_->isChecked());
566 QStringList::iterator it;
567 for (it = lookup_names.begin(); it != lookup_names.end(); ++it)
569 const QString& lookup_name = *it;
573 Q_FOREACH (QString topic_type, topic_types)
576 datatype_plugins_.insertMulti(topic_type, lookup_name);
583 QTreeWidgetItem* current = tree_->invisibleRootItem();
585 QStringList parts = topic.split(
"/");
587 for (
int part_ind = 1; part_ind < parts.size(); ++part_ind)
589 QString part =
"/" + parts[part_ind];
592 for (
int c = 0; c < current->childCount(); ++c)
594 QTreeWidgetItem* child = current->child(c);
595 if (child->text(0) == part && !child->data(1, Qt::UserRole).isValid())
605 QTreeWidgetItem* new_child =
new QTreeWidgetItem(current);
607 new_child->setExpanded(3 > part_ind);
608 new_child->setText(0, part);
609 new_child->setDisabled(disabled);
QMap< QString, Info > plugins
QStringList getDeclaredClassIds() override
virtual QString getClassName(const QString &class_id) const =0
ROSCPP_DECL std::string parentNamespace(const std::string &name)
void fillTree(Factory *factory)
QString getClassDescription(const QString &class_id) const override
void onDisplaySelected(SelectionData *data)
SelectionData display_data_
ROSCPP_DECL bool getTopics(V_TopicInfo &topics)
ROSCPP_DECL bool validate(const std::string &name, std::string &error)
SelectionData topic_data_
std::vector< TopicInfo > V_TopicInfo
QSize sizeHint() const override
virtual QSet< QString > getMessageTypes(const QString &class_id)
Get all supported message types for the given class id.
bool isSubtopic(const std::string &base, const std::string &topic)
QStringList topic_suffixes
AddDisplayDialog(DisplayFactory *factory, const QString &object_type, const QStringList &disallowed_display_names, const QStringList &disallowed_class_lookup_names, QString *lookup_name_output, QString *display_name_output=nullptr, QString *topic_output=nullptr, QString *datatype_output=nullptr, QWidget *parent=nullptr)
virtual QString getClassDescription(const QString &class_id) const =0
const QStringList & disallowed_display_names_
QString getClassName(const QString &class_id) const override
void onCurrentItemChanged(QTreeWidgetItem *curr, QTreeWidgetItem *prev)
void onTopicSelected(SelectionData *data)
void onTabChanged(int index)
Abstract superclass representing the ability to get a list of class IDs and the ability to get name...
QTextBrowser * description_
QString * display_name_output_
QString * datatype_output_
void setError(const QString &error_text)
virtual QIcon getIcon(const QString &class_id) const =0
void getPluginGroups(const QMap< QString, QString > &datatype_plugins, QList< PluginGroup > *groups, QList< ros::master::TopicInfo > *unvisualizable)
#define ROS_ERROR_STREAM(args)
virtual QStringList getDeclaredClassIds()=0
QString * lookup_name_output_
QPixmap loadPixmap(QString url, bool fill_cache)
QIcon getIcon(const QString &class_id) const override
Widget for selecting a display by display type.
QDialogButtonBox * button_box_
bool operator()(const ros::master::TopicInfo &a, const ros::master::TopicInfo &b)