diff --git a/gazebo/gui/plot/Palette.cc b/gazebo/gui/plot/Palette.cc index 4ab3cf4ba2..7a02848d1d 100644 --- a/gazebo/gui/plot/Palette.cc +++ b/gazebo/gui/plot/Palette.cc @@ -870,6 +870,11 @@ void Palette::IntrospectionUpdateSlot(const std::set &_items) // Process path auto pathParts = common::split(pathStr, "/"); + for (auto & part : pathParts) + { + part = common::replaceAll(part, "%2f", "/"); + part = common::replaceAll(part, "%25", "%"); + } QStandardItem *previousItem = nullptr; unsigned int i = 0; diff --git a/gazebo/gui/plot/Palette_TEST.cc b/gazebo/gui/plot/Palette_TEST.cc index e303657ef6..22a4ed4d5a 100644 --- a/gazebo/gui/plot/Palette_TEST.cc +++ b/gazebo/gui/plot/Palette_TEST.cc @@ -112,5 +112,72 @@ void Palette_TEST::ModelsTab() delete palette; } +///////////////////////////////////////////////// +void Palette_TEST::ModelsTabNamesWithSlashes() +{ + this->resMaxPercentChange = 5.0; + this->shareMaxPercentChange = 2.0; + + this->Load("worlds/names_with_slashes.world"); + + // Get the number of models in the world + auto world = gazebo::physics::get_world("default"); + QVERIFY(world != nullptr); + + auto count = world->ModelCount(); + + // Create a new plot window widget + auto palette = new gazebo::gui::Palette(nullptr); + QVERIFY(palette != nullptr); + + // Get the models model + auto modelsModel = + palette->findChild("plotModelsModel"); + QVERIFY(modelsModel != nullptr); + + // Check the model has as many rows as there are top level models, + // plus the title + QCOMPARE(modelsModel->rowCount(), static_cast(count + 1)); + + auto model = modelsModel->item(1); + QCOMPARE(0, model->text().toStdString().compare("double/pendulum_%2f")); + QVERIFY(model->hasChildren()); + + auto jointsLabel = model->child(3); + QVERIFY(!jointsLabel->hasChildren()); + + auto joint1 = model->child(4); + QCOMPARE(0, joint1->text().toStdString().compare("lower/joint")); + QCOMPARE(2, joint1->rowCount()); + + auto joint2 = model->child(5); + QCOMPARE(0, joint2->text().toStdString().compare("upper/joint")); + QCOMPARE(2, joint1->rowCount()); + + auto linksLabel = model->child(6); + QVERIFY(!linksLabel->hasChildren()); + + auto link1 = model->child(7); + QCOMPARE(0, link1->text().toStdString().compare("lower/link")); + QCOMPARE(3, link1->rowCount()); + + auto link2 = model->child(8); + QCOMPARE(0, link2->text().toStdString().compare("upper/link")); + QCOMPARE(3, link2->rowCount()); + + this->ProcessEventsAndDraw(); + + // Get the new models model + modelsModel = + palette->findChild("plotModelsModel"); + QVERIFY(modelsModel != nullptr); + + // Check the model has as many rows as there are top level models, + // plus the title + QCOMPARE(modelsModel->rowCount(), static_cast(count + 1)); + + delete palette; +} + // Generate a main function for the test QTEST_MAIN(Palette_TEST) diff --git a/gazebo/gui/plot/Palette_TEST.hh b/gazebo/gui/plot/Palette_TEST.hh index 9593c78c37..55a088405a 100644 --- a/gazebo/gui/plot/Palette_TEST.hh +++ b/gazebo/gui/plot/Palette_TEST.hh @@ -30,5 +30,8 @@ class Palette_TEST : public QTestFixture /// \brief Test the models tab. private slots: void ModelsTab(); + + /// \brief test that models with slashes in name are handled. + private slots: void ModelsTabNamesWithSlashes(); }; #endif diff --git a/gazebo/physics/Base.cc b/gazebo/physics/Base.cc index 2abd43d0d2..b13b90f5b6 100644 --- a/gazebo/physics/Base.cc +++ b/gazebo/physics/Base.cc @@ -15,6 +15,7 @@ * */ #include "gazebo/common/Assert.hh" +#include "gazebo/common/CommonIface.hh" #include "gazebo/common/Console.hh" #include "gazebo/common/Exception.hh" #include "gazebo/common/SdfFrameSemantics.hh" @@ -383,7 +384,10 @@ common::URI Base::URI() const { if (p->GetParent()) { - uri.Path().PushFront(p->GetName()); + std::string escapedParentName = p->GetName(); + escapedParentName = common::replaceAll(escapedParentName, "%", "%25"); + escapedParentName = common::replaceAll(escapedParentName, "/", "%2f"); + uri.Path().PushFront(escapedParentName); uri.Path().PushFront(p->TypeStr()); } @@ -391,7 +395,10 @@ common::URI Base::URI() const } uri.Path().PushBack(this->TypeStr()); - uri.Path().PushBack(this->GetName()); + std::string escapedName = this->GetName(); + escapedName = common::replaceAll(escapedName, "%", "%25"); + escapedName = common::replaceAll(escapedName, "/", "%2f"); + uri.Path().PushBack(escapedName); uri.Path().PushFront(this->world->Name()); uri.Path().PushFront("world"); diff --git a/test/worlds/names_with_slashes.world b/test/worlds/names_with_slashes.world new file mode 100644 index 0000000000..32cde37c70 --- /dev/null +++ b/test/worlds/names_with_slashes.world @@ -0,0 +1,88 @@ + + + + + 1 0 -9.81 + 0.00101 + + + model://sun + + + + 0 0 0.9 0.7853981633974483 0 0 + + 0 0 -0.05 0 0 0 + + 0.02700000000000001 + + 2.272500000000001e-05 + 2.272500000000001e-05 + 4.5000000000000035e-07 + 0.0 + 0.0 + 0.0 + + + + + + 0.010000000000000002 0.010000000000000002 0.1 + + + + + + + 0.010000000000000002 0.010000000000000002 0.1 + + + + + + 0 0 0.05 0 0 0 + world + upper/link + + 1 0 0 + + + + 0 0.17677669529663687 -0.2767766952966369 0.7853981633974483 0 0 + + 3.375 + + 0.071015625 + 0.071015625 + 0.0014062500000000004 + 0.0 + 0.0 + 0.0 + + + + + + 0.05 0.05 0.5 + + + + + + + 0.05 0.05 0.5 + + + + + + 0 0 0.25 0 0 0 + upper/link + lower/link + + 1 0 0 + + + + +