Skip to content

Commit

Permalink
Enhancement overlays menu (#6297)
Browse files Browse the repository at this point in the history
* Show all robots in Overlays menu

* Improve menus text

* Add entry in ChangeLog

* Remove unused variable

---------

Co-authored-by: Olivier Michel <Olivier.Michel@cyberbotics.com>
  • Loading branch information
stefaniapedrazzi and omichel committed Jul 5, 2023
1 parent 618a6bd commit c8ce1fd
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 112 deletions.
2 changes: 2 additions & 0 deletions docs/reference/changelog-r2023.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Released on XXX XXth, 2023.
- New Devices and Objects
- Added a model of a silo and a field ditch ([#6289](https://github.com/cyberbotics/webots/pull/6289)).
- Enhancements
- Improved overlays visible in Overlays menu by adding all the robots in the menu list ([#6297](https://github.com/cyberbotics/webots/pull/6297)).
- Bug fixes
- Fixed errors loading template PROTO if the system user name, the project path, or the temporary directory path contains the `\` character ([#6288](https://github.com/cyberbotics/webots/pull/6288)).

Expand Down
234 changes: 140 additions & 94 deletions src/webots/gui/WbMainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ WbMainWindow::WbMainWindow(bool minimizedOnStart, WbTcpServer *tcpServer, QWidge

mFactoryLayout = new QByteArray(saveState());

updateGui();
updateWindowTitle();

if (WbPreferences::instance()->value("General/checkWebotsUpdateOnStartup").toBool() && WbMessageBox::enabled()) {
WbWebotsUpdateManager *webotsUpdateManager = WbWebotsUpdateManager::instance();
Expand Down Expand Up @@ -383,8 +383,6 @@ void WbMainWindow::createMainTools() {
setCentralWidget(mSimulationView);
addDock(mSimulationView);
connect(mSimulationView, &WbSimulationView::requestOpenUrl, this, &WbMainWindow::openUrl);
connect(mSimulationView->selection(), &WbSelection::selectionChangedFromSceneTree, this, &WbMainWindow::updateOverlayMenu);
connect(mSimulationView->selection(), &WbSelection::selectionChangedFromView3D, this, &WbMainWindow::updateOverlayMenu);
connect(mSimulationView->sceneTree(), &WbSceneTree::editRequested, this, &WbMainWindow::openFileInTextEditor);
if (mTcpServer) {
mTcpServer->setMainWindow(this);
Expand Down Expand Up @@ -708,17 +706,12 @@ QMenu *WbMainWindow::createOverlayMenu() {
mOverlayMenu = new QMenu(this);
mOverlayMenu->setTitle(tr("&Overlays"));

mRobotCameraMenu = mOverlayMenu->addMenu(tr("Ca&mera Devices"));
mRobotRangeFinderMenu = mOverlayMenu->addMenu(tr("&RangeFinder Devices"));
mRobotDisplayMenu = mOverlayMenu->addMenu(tr("&Display Devices"));

WbContextMenuGenerator::setRobotCameraMenu(mRobotCameraMenu);
WbContextMenuGenerator::setRobotRangeFinderMenu(mRobotRangeFinderMenu);
WbContextMenuGenerator::setRobotDisplayMenu(mRobotDisplayMenu);

mOverlayMenu->addAction(WbActionManager::instance()->action(WbAction::HIDE_ALL_CAMERA_OVERLAYS));
mOverlayMenu->addAction(WbActionManager::instance()->action(WbAction::HIDE_ALL_RANGE_FINDER_OVERLAYS));
mOverlayMenu->addAction(WbActionManager::instance()->action(WbAction::HIDE_ALL_DISPLAY_OVERLAYS));
mOverlayMenu->addSeparator();

WbContextMenuGenerator::setOverlaysMenu(mOverlayMenu);

return mOverlayMenu;
}
Expand Down Expand Up @@ -1023,6 +1016,11 @@ void WbMainWindow::closeEvent(QCloseEvent *event) {

logActiveControllersTermination();

if (WbWorld::instance()) {
disconnect(WbWorld::instance(), &WbWorld::robotAdded, this, &WbMainWindow::addRobotInOverlaysMenu);
disconnect(WbWorld::instance(), &WbWorld::robotRemoved, this, &WbMainWindow::removeRobotInOverlaysMenu);
}

// disconnect from file changed signal before saving the perspective
// if the perspective file is open, a segmentation fault is generated
// due to double free of the reload QMessageBox on Linux
Expand Down Expand Up @@ -1259,6 +1257,7 @@ void WbMainWindow::restoreRenderingDevicesPerspective() {
device->restorePerspective(devicePerspective);
}
disconnect(mSimulationView->view3D(), &WbView3D::resized, this, &WbMainWindow::restoreRenderingDevicesPerspective);
updateOverlayMenu();
}

void WbMainWindow::loadDifferentWorld(const QString &fileName) {
Expand Down Expand Up @@ -1311,6 +1310,10 @@ void WbMainWindow::loadWorld(const QString &fileName, bool reloading) {
return;
}
mSimulationView->cancelSupervisorMovieRecording();
if (WbWorld::instance()) {
disconnect(WbWorld::instance(), &WbWorld::robotAdded, this, &WbMainWindow::addRobotInOverlaysMenu);
disconnect(WbWorld::instance(), &WbWorld::robotRemoved, this, &WbMainWindow::removeRobotInOverlaysMenu);
}
logActiveControllersTermination();
WbLog::setConsoleLogsPostponed(true);
WbApplication::instance()->loadWorld(fileName, reloading);
Expand Down Expand Up @@ -1376,8 +1379,11 @@ void WbMainWindow::updateAfterWorldLoading(bool reloading, bool firstLoad) {

connect(world, &WbWorld::modificationChanged, this, &WbMainWindow::updateWindowTitle);
connect(world, &WbWorld::resetRequested, this, &WbMainWindow::resetGui, Qt::QueuedConnection);
// update 'overlays' menu
connect(WbWorld::instance(), &WbWorld::robotAdded, this, &WbMainWindow::addRobotInOverlaysMenu);
connect(WbWorld::instance(), &WbWorld::robotRemoved, this, &WbMainWindow::removeRobotInOverlaysMenu);

updateGui();
updateWindowTitle();

if (!reloading)
WbActionManager::instance()->resetApplicationActionsState();
Expand Down Expand Up @@ -2107,11 +2113,6 @@ void WbMainWindow::updateWindowTitle() {
setWindowTitle(title);
}

void WbMainWindow::updateGui() {
updateWindowTitle();
updateOverlayMenu();
}

void WbMainWindow::simulationEnabledChanged(bool e) {
mSimulationMenu->setEnabled(e);
}
Expand Down Expand Up @@ -2226,91 +2227,136 @@ void WbMainWindow::deleteRobotWindow(WbRobot *robot) {
mOnSocketOpen = true;
}

static bool isRobotNode(WbBaseNode *node) {
return dynamic_cast<WbRobot *>(node);
void WbMainWindow::clearOverlaysMenu() {
QList<QAction *> actions = mOverlayMenu->actions();
while (actions.size() > 4) {
QAction *action = actions.last();
if (action->menu())
mOverlayMenu->removeAction(action);
actions.removeLast();
}
}

void WbMainWindow::updateOverlayMenu() {
QList<QAction *> actions;
WbRobot *selectedRobot = mSimulationView->selectedRobot();

// remove camera and display item list
actions = mRobotCameraMenu->actions();
for (int i = 0; i < actions.size(); ++i) {
mRobotCameraMenu->removeAction(actions[i]);
delete actions[i];
}
actions = mRobotRangeFinderMenu->actions();
for (int i = 0; i < actions.size(); ++i) {
mRobotRangeFinderMenu->removeAction(actions[i]);
delete actions[i];
}
actions = mRobotDisplayMenu->actions();
for (int i = 0; i < actions.size(); ++i) {
mRobotDisplayMenu->removeAction(actions[i]);
delete actions[i];
}

// add current robot and descendant robot specific camera and display items
if (selectedRobot) {
QAction *action = NULL;
bool hasDisplay = false;
bool hasCamera = false;
bool hasRangeFinder = false;
QList<WbNode *> robotList = WbNodeUtilities::findDescendantNodesOfType(selectedRobot, isRobotNode, true);
robotList.prepend(selectedRobot);
foreach (WbNode *robotNode, robotList) {
WbRobot *robot = reinterpret_cast<WbRobot *>(robotNode);
QList<WbRenderingDevice *> devices = robot->renderingDevices();
for (int i = 0; i < devices.size(); ++i) {
const WbRenderingDevice *device = devices[i];
QString deviceName = device->name();
void WbMainWindow::updateRobotNameInOverlaysMenu() {
const WbRobot *robot = static_cast<WbRobot *>(sender());
QListIterator<QAction *> it(mOverlayMenu->actions());
while (it.hasNext()) {
const QAction *action = it.next();
QMenu *menu = action->menu();
if (menu && menu->property("robot").value<void *>() == robot) {
QString robotName = robot->name();
#ifdef __linux__
// fix Unity bug with underscores in menu item text
if (qgetenv("XDG_CURRENT_DESKTOP") == "Unity")
deviceName.replace("_", "__");
// fix Unity bug with underscores in menu item text
if (qgetenv("XDG_CURRENT_DESKTOP") == "Unity")
robotName.replace("_", "__");
#endif
action = new QAction(this);
if (robot != selectedRobot)
action->setText(tr("Show '%2' overlay of robot '%1'").arg(robot->name()).arg(deviceName));
else
action->setText(tr("Show '%1' overlay").arg(deviceName));
if (device->nodeType() == WB_NODE_CAMERA) {
action->setStatusTip(tr("Show overlay of camera device '%1'.").arg(deviceName));
mRobotCameraMenu->addAction(action);
hasCamera = true;
} else if (device->nodeType() == WB_NODE_RANGE_FINDER) {
action->setStatusTip(tr("Show overlay of range-finder device '%1'.").arg(deviceName));
mRobotRangeFinderMenu->addAction(action);
hasRangeFinder = true;
} else if (device->nodeType() == WB_NODE_DISPLAY) {
action->setStatusTip(tr("Show overlay of display device '%1'.").arg(deviceName));
mRobotDisplayMenu->addAction(action);
hasDisplay = true;
} else {
delete action;
continue;
}
action->setToolTip(mToggleFullScreenAction->statusTip());
action->setCheckable(true);
action->setChecked(device->isOverlayEnabled());
action->setEnabled(!device->isWindowActive());
action->setProperty("renderingDevice",
QVariant::fromValue(static_cast<void *>(const_cast<WbRenderingDevice *>(device))));
connect(action, &QAction::toggled, mSimulationView->view3D(), &WbView3D::setShowRenderingDevice);
connect(device, &WbRenderingDevice::overlayVisibilityChanged, action, &QAction::setChecked);
connect(device, &WbRenderingDevice::overlayStatusChanged, action, &QAction::setEnabled);
}
menu->setTitle(tr("'%1' Overlays").arg(robotName));
}
}
}

mRobotDisplayMenu->setEnabled(hasDisplay);
mRobotCameraMenu->setEnabled(hasCamera);
mRobotRangeFinderMenu->setEnabled(hasRangeFinder);
void WbMainWindow::removeRobotInOverlaysMenu(const WbRobot *robot) {
QListIterator<QAction *> it(mOverlayMenu->actions());
while (it.hasNext()) {
QAction *action = it.next();
const QMenu *menu = action->menu();
if (menu && menu->property("robot").value<void *>() == robot) {
mOverlayMenu->removeAction(action);
return;
}
}
}

void WbMainWindow::addRobotInOverlaysMenu(WbRobot *robot) {
QAction *action = NULL;
QList<QAction *> cameraActions;
QList<QAction *> rangeFinderActions;
QList<QAction *> displayActions;

QString robotName = robot->name();
#ifdef __linux__
// fix Unity bug with underscores in menu item text
if (qgetenv("XDG_CURRENT_DESKTOP") == "Unity")
robotName.replace("_", "__");
#endif
QMenu *robotMenu = mOverlayMenu->addMenu(tr("'%1' Overlays").arg(robotName));
robotMenu->setProperty("robot", QVariant::fromValue(static_cast<void *>(const_cast<WbRobot *>(robot))));
connect(robot, &WbMatter::matterNameChanged, this, &WbMainWindow::updateRobotNameInOverlaysMenu);

QListIterator<WbRenderingDevice *> devicesIt(robot->renderingDevices());
while (devicesIt.hasNext()) {
const WbRenderingDevice *device = devicesIt.next();
QString deviceName = device->name();
#ifdef __linux__
// fix Unity bug with underscores in menu item text
if (qgetenv("XDG_CURRENT_DESKTOP") == "Unity")
deviceName.replace("_", "__");
#endif
action = new QAction(this);
action->setText(tr("Show '%1' Overlay").arg(deviceName));
if (device->nodeType() == WB_NODE_CAMERA) {
action->setStatusTip(tr("Show overlay of camera device '%1' for robot '%2'.").arg(deviceName).arg(robotName));
cameraActions << action;
} else if (device->nodeType() == WB_NODE_RANGE_FINDER) {
action->setStatusTip(tr("Show overlay of range-finder device '%1' for robot '%2'.").arg(deviceName).arg(robotName));
rangeFinderActions << action;
} else if (device->nodeType() == WB_NODE_DISPLAY) {
action->setStatusTip(tr("Show overlay of display device '%1' for robot '%2'.").arg(deviceName).arg(robotName));
displayActions << action;
} else {
delete action;
continue;
}
action->setToolTip(mToggleFullScreenAction->statusTip());
action->setCheckable(true);
action->setChecked(device->isOverlayEnabled());
action->setEnabled(!device->isWindowActive());
action->setProperty("renderingDevice", QVariant::fromValue(static_cast<void *>(const_cast<WbRenderingDevice *>(device))));
connect(action, &QAction::toggled, mSimulationView->view3D(), &WbView3D::setShowRenderingDevice);
connect(device, &WbRenderingDevice::overlayVisibilityChanged, action, &QAction::setChecked);
connect(device, &WbRenderingDevice::overlayStatusChanged, action, &QAction::setEnabled);
}

if (cameraActions.isEmpty() && rangeFinderActions.isEmpty() && displayActions.isEmpty()) {
robotMenu->setEnabled(false);
return;
}

QMenu *cameraMenu = robotMenu->addMenu(tr("Camera Devices"));
if (cameraActions.isEmpty())
cameraMenu->setEnabled(false);
else {
QListIterator<QAction *> actionIt(cameraActions);
while (actionIt.hasNext())
cameraMenu->addAction(actionIt.next());
}
QMenu *rangeFinderMenu = robotMenu->addMenu(tr("RangeFinder Devices"));
if (rangeFinderActions.isEmpty())
rangeFinderMenu->setEnabled(false);
else {
QListIterator<QAction *> actionIt(rangeFinderActions);
while (actionIt.hasNext())
rangeFinderMenu->addAction(actionIt.next());
}
QMenu *displayMenu = robotMenu->addMenu(tr("Display Devices"));
if (displayActions.isEmpty())
displayMenu->setEnabled(false);
else {
QListIterator<QAction *> actionIt(displayActions);
while (actionIt.hasNext())
displayMenu->addAction(actionIt.next());
}
}

void WbMainWindow::updateOverlayMenu() {
clearOverlaysMenu();

if (!WbWorld::instance())
return;

actions = mOverlayMenu->actions();
for (int i = 0; i < actions.size() - 3; ++i)
actions[i]->setVisible(selectedRobot != NULL);
QListIterator<WbRobot *> robotIt(WbWorld::instance()->robots());
while (robotIt.hasNext())
addRobotInOverlaysMenu(robotIt.next());
}

void WbMainWindow::updateProjectPath(const QString &oldPath, const QString &newPath) {
Expand Down
5 changes: 4 additions & 1 deletion src/webots/gui/WbMainWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ private slots:
void showStatusBarMessage(WbLog::Level level, const QString &message);
void editRobotController();
void showRobotWindow();
void clearOverlaysMenu();
void updateOverlayMenu();
void updateRobotNameInOverlaysMenu();
void addRobotInOverlaysMenu(WbRobot *robot);
void removeRobotInOverlaysMenu(const WbRobot *robot);
void createWorldLoadingProgressDialog();
void deleteWorldLoadingProgressDialog();
void setWorldLoadingProgress(const int progress);
Expand Down Expand Up @@ -198,7 +202,6 @@ private slots:
QString findHtmlFileName(const char *title);
void enableToolsWidgetItems(bool enabled);
void updateWindowTitle();
void updateGui();
void updateSimulationMenu();
void writePreferences() const;
void showDocument(const QString &url);
Expand Down
1 change: 1 addition & 0 deletions src/webots/nodes/utils/WbWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ void WbWorld::removeRobotIfPresent(WbRobot *robot) {
return;

mRobots.removeAll(robot);
emit robotRemoved(robot);
}

void WbWorld::addRobotIfNotAlreadyPresent(WbRobot *robot) {
Expand Down
1 change: 1 addition & 0 deletions src/webots/nodes/utils/WbWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class WbWorld : public QObject {
void worldLoadingHasProgressed(int percent);
void viewpointChanged();
void robotAdded(WbRobot *robot);
void robotRemoved(WbRobot *robot);
void resetRequested(bool restartControllers);

public slots:
Expand Down
Loading

0 comments on commit c8ce1fd

Please sign in to comment.