GCC Code Coverage Report


Directory: ./
File: src/gui/mainwindow.cc
Date: 2025-04-14 11:18:00
Exec Total Coverage
Lines: 0 347 0.0%
Branches: 0 674 0.0%

Line Branch Exec Source
1 // Copyright (c) 2015-2018, LAAS-CNRS
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4 // This file is part of gepetto-viewer.
5 // gepetto-viewer is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // gepetto-viewer is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // gepetto-viewer. If not, see <http://www.gnu.org/licenses/>.
16
17 #include "gepetto/gui/mainwindow.hh"
18
19 #include <QMessageBox>
20 #include <QScrollBar>
21 #include <QtGlobal>
22 #include <sstream>
23
24 #include "ui_mainwindow.h"
25 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
26 #include <QtConcurrent>
27 #endif
28
29 #include <gepetto/gui/config-dep.hh>
30 #include <osg/Version>
31
32 #include "gepetto/gui/action-search-bar.hh"
33 #include "gepetto/gui/dialog/dialogloadenvironment.hh"
34 #include "gepetto/gui/dialog/dialogloadrobot.hh"
35 #include "gepetto/gui/node-action.hh"
36 #include "gepetto/gui/osgwidget.hh"
37 #include "gepetto/gui/plugin-interface.hh"
38 #include "gepetto/gui/selection-handler.hh"
39 #include "gepetto/gui/shortcut-factory.hh"
40 #include "gepetto/gui/tree-item.hh"
41 #include "gepetto/gui/windows-manager.hh"
42
43 #if GEPETTO_GUI_HAS_PYTHONQT
44 #include <gepetto/gui/pythonwidget.hh>
45 #endif
46
47 #include "../log.hh"
48
49 namespace gepetto {
50 namespace gui {
51 MainWindow* MainWindow::instance_ = NULL;
52
53 ✗ MainWindow::MainWindow(Settings* settings, QWidget* parent)
54 : QMainWindow(parent),
55 ✗ settings_(settings),
56 ✗ ui_(new ::Ui::MainWindow),
57 ✗ centralWidget_(),
58 ✗ osgViewerManagers_(),
59 ✗ worker_(),
60 ✗ actionSearchBar_(new ActionSearchBar(this)) {
61 ✗ MainWindow::instance_ = this;
62 ✗ ui_->setupUi(this);
63
64 // Setup the body tree view
65 ✗ osgViewerManagers_ = WindowsManager::create(ui_->bodyTreeContent);
66 ✗ ui_->bodyTreeContent->init(ui_->bodyTree, ui_->propertyArea);
67
68 // This scene contains elements required for User Interaction.
69 ✗ osg()->createScene("gepetto-gui");
70 // TODO remove me. This is kept for backward compatibility
71 ✗ osg()->createScene("hpp-gui");
72
73 // Setup the main OSG widget
74 ✗ connect(ui_->actionRefresh, SIGNAL(triggered()), SLOT(requestRefresh()));
75
76 ✗ collisionLabel_ = new QLabel("No collisions.");
77 ✗ shortcutFactory_ = new ShortcutFactory;
78 #if GEPETTO_GUI_HAS_PYTHONQT
79 ✗ pythonWidget_ = new PythonWidget(this);
80 #endif
81 ✗ setupInterface();
82 ✗ connect(ui_->actionChange_shortcut, SIGNAL(triggered()), shortcutFactory_,
83 SLOT(open()));
84
85 ✗ selectionHandler_ = new SelectionHandler(osgViewerManagers_);
86 ✗ selectionHandler_->addMode(new MultiSelection(osgViewerManagers_));
87 ✗ selectionHandler_->addMode(new UniqueSelection(osgViewerManagers_));
88
89 ✗ ui_->mainToolBar->addWidget(selectionHandler_);
90 }
91
92 ✗ MainWindow::~MainWindow() {
93 ✗ delete shortcutFactory_;
94 #if GEPETTO_GUI_HAS_PYTHONQT
95 ✗ removeDockWidget(pythonWidget_);
96 ✗ delete pythonWidget_;
97 #endif
98 ✗ pluginManager()->clearPlugins();
99 ✗ osgViewerManagers_.reset();
100 ✗ worker_.quit();
101 ✗ worker_.wait();
102 ✗ delete ui_;
103 }
104
105 ✗ MainWindow* MainWindow::instance() { return instance_; }
106
107 ✗ void MainWindow::insertDockWidget(QDockWidget* dock, Qt::DockWidgetArea area,
108 Qt::Orientation orientation) {
109 ✗ addDockWidget(area, dock, orientation);
110 ✗ dock->setVisible(false);
111 ✗ dock->toggleViewAction()->setIcon(QIcon::fromTheme("window-new"));
112 ✗ dock->adjustSize();
113 ✗ ui_->menuWindow->addAction(dock->toggleViewAction());
114 ✗ actionSearchBar_->addAction(dock->toggleViewAction());
115 ✗ connect(dock, SIGNAL(visibilityChanged(bool)),
116 SLOT(dockVisibilityChanged(bool)));
117 }
118
119 ✗ void MainWindow::removeDockWidget(QDockWidget* dock) {
120 ✗ ui_->menuWindow->removeAction(dock->toggleViewAction());
121 ✗ disconnect(dock);
122 ✗ QMainWindow::removeDockWidget(dock);
123 }
124
125 ✗ WindowsManagerPtr_t MainWindow::osg() const { return osgViewerManagers_; }
126
127 ✗ BodyTreeWidget* MainWindow::bodyTree() const { return ui_->bodyTreeContent; }
128
129 ✗ QList<OSGWidget*> MainWindow::osgWindows() const { return osgWindows_; }
130
131 ✗ PluginManager* MainWindow::pluginManager() {
132 ✗ return &(settings_->pluginManager_);
133 }
134
135 ✗ ActionSearchBar* MainWindow::actionSearchBar() const {
136 ✗ return actionSearchBar_;
137 }
138
139 ✗ void MainWindow::log(const QString& text) {
140 ✗ if (thread() != QThread::currentThread()) {
141 ✗ emit logString(text);
142 ✗ return;
143 }
144 ✗ ui_->logText->insertHtml("<hr/><font color=black>" + text + "</font>");
145 }
146
147 ✗ void MainWindow::logError(const QString& text) {
148 ✗ if (thread() != QThread::currentThread()) {
149 ✗ emit logErrorString(text);
150 ✗ return;
151 }
152 ✗ if (!ui_->dockWidget_log->isVisible()) {
153 ✗ ui_->dockWidget_log->show();
154 }
155 ✗ QScrollBar* sb = ui_->logText->verticalScrollBar();
156 ✗ bool SBwasAtBottom = sb->value() == sb->maximum();
157 ✗ ui_->logText->insertHtml("<hr/><font color=red>" + text + "</font>");
158 ✗ if (SBwasAtBottom) sb->setValue(sb->maximum());
159 }
160
161 ✗ QMenu* MainWindow::pluginMenu() const { return ui_->menuWindow; }
162
163 ✗ void MainWindow::logJobStarted(int id, const QString& text) {
164 ✗ emit logString(QString("Starting job ") + QString::number(id) + ": " + text);
165 }
166
167 ✗ void MainWindow::logJobDone(int id, const QString& text) {
168 ✗ emit logString(QString("Job ") + QString::number(id) + " done: " + text);
169 }
170
171 ✗ void MainWindow::logJobFailed(int id, const QString& text) {
172 ✗ emit logErrorString(QString("Job ") + QString::number(id) +
173 ✗ " failed: " + text);
174 }
175
176 ✗ OSGWidget* MainWindow::createView(const std::string& name) {
177 ✗ if (thread() != QThread::currentThread()) {
178 ✗ qDebug() << "createView must be called from the main thread.";
179 ✗ throw std::runtime_error("Cannot create a new window.");
180 }
181 ✗ OSGWidget* osgWidget = new OSGWidget(osgViewerManagers_, name, this, 0
182 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
183 ,
184 osgViewer::Viewer::SingleThreaded
185 #endif
186 ✗ );
187 ✗ osgWidget->setObjectName(name.c_str());
188 ✗ addOSGWidget(osgWidget);
189 ✗ emit viewCreated(osgWidget);
190 ✗ return osgWidget;
191 }
192
193 ✗ void MainWindow::requestRefresh() { emit refresh(); }
194
195 ✗ void MainWindow::createDefaultView() {
196 ✗ std::stringstream ss;
197 ✗ ss << "View " << osgWindows_.size();
198 ✗ createView(ss.str());
199 }
200
201 ✗ void MainWindow::addOSGWidget(OSGWidget* osgWidget) {
202 QDockWidget* dockOSG =
203 ✗ new QDockWidget(tr("Window ") + osgWidget->objectName(), this);
204 ✗ dockOSG->setObjectName("gepetto-gui.osg." + osgWidget->objectName());
205 ✗ dockOSG->setWidget(osgWidget);
206 ✗ dockOSG->setSizePolicy(QSizePolicy::MinimumExpanding,
207 QSizePolicy::MinimumExpanding);
208 // TODO at the moment, when the widget is made floating and then non-floating
209 // again, the OSGWidget becomes hidden. I could not find the bug so I removed
210 // the feature DockWidgetFloatable.
211 ✗ dockOSG->setFeatures(QDockWidget::DockWidgetClosable |
212 QDockWidget::DockWidgetMovable);
213 ✗ connect(dockOSG, SIGNAL(visibilityChanged(bool)),
214 SLOT(dockVisibilityChanged(bool)));
215 ✗ addDockWidget(Qt::RightDockWidgetArea, dockOSG);
216 ✗ if (osgWindows_.empty()) {
217 // This OSGWidget should be the central view
218 ✗ centralWidget_ = osgWidget;
219 ✗ osg()->addSceneToWindow("gepetto-gui", centralWidget_->windowID());
220 // TODO remove me. This is kept for backward compatibility
221 ✗ osg()->addSceneToWindow("hpp-gui", centralWidget_->windowID());
222 }
223 ✗ actionSearchBar_->addAction(new NodeAction(
224 ✗ "Attach camera " + osgWidget->objectName() + " to selected node",
225 ✗ osgWidget, this));
226 ✗ osgWidget->addAction(actionSearchBar_->showAction());
227 ✗ osgWindows_.append(osgWidget);
228 ✗ settings_->restoreDockWidgetsState();
229 // When creating a window from Python, it isn't desirable to create a
230 // hidden window. We overwrite the visibility.
231 ✗ dockOSG->show();
232
233 // Add the widget to the window list.
234 ✗ QMenu* views3D = ui_->menuWindow->findChild<QMenu*>("3d views"
235 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
236 ,
237 Qt::FindDirectChildrenOnly
238 #endif
239 );
240 ✗ views3D->addAction(dockOSG->toggleViewAction());
241 }
242
243 ✗ void MainWindow::openLoadRobotDialog() {
244 ✗ statusBar()->showMessage("Loading a robot...");
245 ✗ DialogLoadRobot* d = new DialogLoadRobot(this);
246 ✗ if (d->exec() == QDialog::Accepted) {
247 ✗ createCentralWidget();
248 ✗ DialogLoadRobot::RobotDefinition rd = d->getSelectedRobotDescription();
249
250 ✗ QString urdfFile = QString("package://%1/urdf/%2%3.urdf")
251 ✗ .arg(rd.package_)
252 ✗ .arg(rd.modelName_)
253 ✗ .arg(rd.urdfSuf_);
254 try {
255 ✗ osgViewerManagers_->addURDF(rd.robotName_.toStdString(),
256 ✗ urdfFile.toStdString());
257 ✗ osgViewerManagers_->addSceneToWindow(rd.robotName_.toStdString(),
258 ✗ centralWidget_->windowID());
259 ✗ } catch (std::runtime_error& exc) {
260 ✗ logError(exc.what());
261 }
262 ✗ robotNames_.append(rd.robotName_);
263
264 ✗ QString what = QString("Loading robot ") + rd.name_;
265 ✗ foreach (ModelInterface* loader, pluginManager()->get<ModelInterface>()) {
266 ✗ QtConcurrent::run(loader, &ModelInterface::loadRobotModel, rd);
267 ✗ logString(what);
268 }
269 }
270 ✗ d->close();
271 ✗ statusBar()->clearMessage();
272 ✗ d->deleteLater();
273 }
274
275 ✗ void MainWindow::openLoadEnvironmentDialog() {
276 ✗ statusBar()->showMessage("Loading an environment...");
277 ✗ DialogLoadEnvironment* e = new DialogLoadEnvironment(this);
278 ✗ if (e->exec() == QDialog::Accepted) {
279 ✗ createCentralWidget();
280 DialogLoadEnvironment::EnvironmentDefinition ed =
281 ✗ e->getSelectedDescription();
282
283 ✗ QString urdfFile = QString("package://%1/urdf/%2.urdf")
284 ✗ .arg(ed.package_)
285 ✗ .arg(ed.urdfFilename_);
286 try {
287 ✗ osgViewerManagers_->addUrdfObjects(ed.envName_.toStdString(),
288 ✗ urdfFile.toStdString(), true);
289 ✗ osgViewerManagers_->addSceneToWindow(ed.envName_.toStdString(),
290 ✗ centralWidget_->windowID());
291 ✗ } catch (std::runtime_error& exc) {
292 ✗ log(exc.what());
293 }
294
295 ✗ QString what = QString("Loading environment ") + ed.name_;
296 ✗ foreach (ModelInterface* loader, pluginManager()->get<ModelInterface>()) {
297 ✗ QtConcurrent::run(loader, &ModelInterface::loadEnvironmentModel, ed);
298 ✗ logString(what);
299 }
300 }
301 ✗ statusBar()->clearMessage();
302 ✗ e->close();
303 ✗ e->deleteLater();
304 }
305
306 ✗ void MainWindow::handleWorkerDone(int /*id*/) {}
307
308 ✗ void MainWindow::resetConnection() {
309 ✗ foreach (ConnectionInterface* e,
310 pluginManager()->get<ConnectionInterface>()) {
311 ✗ e->openConnection();
312 }
313 }
314
315 ✗ void MainWindow::closeConnection() {
316 ✗ foreach (ConnectionInterface* e,
317 pluginManager()->get<ConnectionInterface>()) {
318 ✗ e->closeConnection();
319 }
320 }
321
322 #define _to_str_(a) #a
323 #define _to_str(a) _to_str_(a)
324 #define _osg_version_str \
325 _to_str(OPENSCENEGRAPH_MAJOR_VERSION) "." _to_str( \
326 OPENSCENEGRAPH_MINOR_VERSION) "." _to_str(OPENSCENEGRAPH_PATCH_VERSION)
327
328 ✗ void MainWindow::about() {
329 ✗ QString devString;
330 devString =
331 ✗ trUtf8(
332 "<p>Version %1. For more information visit <a href=\"%2\">%2</a></p>"
333 "<p><ul>"
334 "<li>Compiled with Qt %3, run with Qt %4</li>"
335 "<li>Compiled with OpenSceneGraph version " _osg_version_str
336 ", run with version %5</li>"
337 #if GEPETTO_GUI_HAS_PYTHONQT
338 "<li>Compiled with PythonQt.</li>"
339 #else
340 "<li>Compiled without PythonQt</li>"
341 #endif
342 "<li></li>"
343 "<li></li>"
344 "</ul></p>"
345 "<p><small>Copyright (c) 2013-2020 CNRS<br/>By Joseph Mirabel and "
346 "others.</small></p>"
347 "<p><small>"
348 "BSD 2-Clause License<br/>"
349 "All rights reserved.<br/><br/>"
350 "Redistribution and use in source and binary forms, with or without"
351 "modification, are permitted provided that the following conditions "
352 "are met:"
353 "<ol><li>Redistributions of source code must retain the above "
354 "copyright notice, this"
355 "list of conditions and the following disclaimer.</li>"
356 "<li>Redistributions in binary form must reproduce the above "
357 "copyright notice,"
358 "this list of conditions and the following disclaimer in the "
359 "documentation"
360 "and/or other materials provided with the distribution.</li></ol>"
361 "</small></p>")
362 ✗ .arg(QApplication::applicationVersion())
363 ✗ .arg(QApplication::organizationDomain())
364 ✗ .arg(QT_VERSION_STR)
365 ✗ .arg(qVersion())
366 ✗ .arg(osgGetVersion());
367
368 ✗ QMessageBox::about(this, QApplication::applicationName(), devString);
369 }
370
371 #undef _to_str
372 #undef _osg_version_str
373
374 ✗ void MainWindow::activateCollision(bool activate) {
375 ✗ if (activate) {
376 ✗ requestConfigurationValidation();
377 ✗ foreach (QString b, lastBodiesInCollision_) {
378 ✗ osg()->setHighlight(b.toLocal8Bit().data(), 1);
379 }
380 } else {
381 ✗ foreach (QString b, lastBodiesInCollision_) {
382 ✗ osg()->setHighlight(b.toLocal8Bit().data(), 0);
383 }
384 ✗ collisionIndicator_->switchLed(true);
385 ✗ collisionLabel_->setText("No collisions.");
386 }
387 }
388
389 ✗ void MainWindow::dockVisibilityChanged(bool visible) {
390 ✗ QWidget* cw = centralWidget();
391 ✗ if (visible && cw->isVisible())
392 ✗ cw->hide();
393 else {
394 ✗ const QObjectList& objs = children();
395 ✗ foreach (const QObject* obj, objs) {
396 ✗ const QDockWidget* dock = qobject_cast<const QDockWidget*>(obj);
397 ✗ if (dock != 0 && dock->isVisible()) return;
398 }
399 ✗ cw->show();
400 }
401 }
402
403 ✗ void MainWindow::hsplitTabifiedDockWidget() {
404 ✗ splitTabifiedDockWidget(Qt::Horizontal);
405 }
406
407 ✗ void MainWindow::vsplitTabifiedDockWidget() {
408 ✗ splitTabifiedDockWidget(Qt::Vertical);
409 }
410
411 ✗ QDockWidget* getParentDockWidget(QObject* child) {
412 ✗ QDockWidget* dock = NULL;
413 ✗ while (child != NULL) {
414 ✗ dock = qobject_cast<QDockWidget*>(child);
415 ✗ if (dock != NULL) break;
416 ✗ child = child->parent();
417 }
418 ✗ return dock;
419 }
420
421 ✗ void MainWindow::splitTabifiedDockWidget(Qt::Orientation orientation) {
422 // QDockWidget focused
423 ✗ QDockWidget* dock = getParentDockWidget(QApplication::focusWidget());
424 ✗ if (dock == NULL) return;
425 // QDockWidget under cursor
426 QDockWidget* other =
427 ✗ getParentDockWidget(QApplication::widgetAt(QCursor::pos()));
428 ✗ if (other == NULL) return;
429 ✗ if (other == dock) return;
430 ✗ splitDockWidget(dock, other, orientation);
431 }
432
433 ✗ void MainWindow::setupInterface() {
434 // Menu "Window/Tool bar"
435 ✗ QMenu* toolbar = ui_->menuWindow->addMenu("Tool bar");
436 ✗ toolbar->setIcon(QIcon::fromTheme("configure-toolbars"));
437 ✗ ui_->mainToolBar->setVisible(true);
438 ✗ toolbar->addAction(ui_->mainToolBar->toggleViewAction());
439
440 ✗ ui_->menuWindow->addSeparator();
441
442 // Menu "Window/3D views"
443 ✗ QMenu* views3D = ui_->menuWindow->addMenu("3D views");
444 ✗ views3D->setObjectName("3d views");
445
446 ✗ ui_->menuWindow->addSeparator();
447
448 // Menu "Window"
449 ✗ ui_->dockWidget_bodyTree->setVisible(false);
450 ✗ ui_->dockWidget_bodyTree->toggleViewAction()->setIcon(
451 ✗ QIcon::fromTheme("window-new"));
452 ✗ ui_->dockWidget_bodyTree->toggleViewAction()->setShortcut(Qt::CTRL + Qt::ALT +
453 Qt::Key_B);
454 ✗ ui_->menuWindow->addAction(ui_->dockWidget_bodyTree->toggleViewAction());
455 ✗ ui_->dockWidget_log->setVisible(false);
456 ✗ ui_->dockWidget_log->toggleViewAction()->setIcon(
457 ✗ QIcon::fromTheme("window-new"));
458 ✗ ui_->dockWidget_log->toggleViewAction()->setShortcut(Qt::CTRL + Qt::ALT +
459 Qt::Key_L);
460 ✗ ui_->menuWindow->addAction(ui_->dockWidget_log->toggleViewAction());
461 #if GEPETTO_GUI_HAS_PYTHONQT
462 ✗ insertDockWidget(pythonWidget_, Qt::BottomDockWidgetArea, Qt::Horizontal);
463 ✗ registerShortcut("Python console", "Toggle view",
464 ✗ pythonWidget_->toggleViewAction());
465 #endif
466
467 // Add QActions to split dock widgets
468 ✗ QAction* vsplit = new QAction("Split focused dock widget vertically", this);
469 ✗ vsplit->setShortcut(Qt::CTRL + Qt::Key_S);
470 ✗ addAction(vsplit);
471 ✗ connect(vsplit, SIGNAL(triggered()), SLOT(vsplitTabifiedDockWidget()));
472 ✗ QAction* hsplit = new QAction("Split focused dock widget horizontally", this);
473 ✗ hsplit->setShortcut(Qt::CTRL + Qt::Key_H);
474 ✗ addAction(hsplit);
475 ✗ connect(hsplit, SIGNAL(triggered()), SLOT(hsplitTabifiedDockWidget()));
476
477 ✗ registerShortcut("Log widget", "Toggle view",
478 ✗ ui_->dockWidget_log->toggleViewAction());
479 ✗ registerShortcut("Body tree widget", "Toggle view",
480 ✗ ui_->dockWidget_bodyTree->toggleViewAction());
481 ✗ registerShortcut("Main window", ui_->actionLoad_robot_from_file);
482 ✗ registerShortcut("Main window", ui_->actionLoad_environment);
483 ✗ registerShortcut("Main window", ui_->actionChange_shortcut);
484 ✗ registerShortcut("Main window", ui_->actionQuit);
485 ✗ registerShortcut("Main window", ui_->actionReconnect);
486 ✗ registerShortcut("Main window", ui_->actionRefresh);
487 ✗ registerShortcut("Main window", ui_->actionPlugins);
488 ✗ registerShortcut("Main window", vsplit);
489 ✗ registerShortcut("Main window", hsplit);
490
491 ✗ ui_->menuWindow->addSeparator();
492
493 // Setup the status bar
494 ✗ collisionIndicator_ = new LedIndicator(statusBar());
495 ✗ collisionValidationActivated_ = new QCheckBox();
496 ✗ collisionValidationActivated_->setToolTip(
497 ✗ tr("Automatically validate configurations."));
498 ✗ collisionValidationActivated_->setCheckState(Qt::Checked);
499 ✗ statusBar()->addPermanentWidget(collisionLabel_);
500 ✗ statusBar()->addPermanentWidget(collisionValidationActivated_);
501 ✗ statusBar()->addPermanentWidget(collisionIndicator_);
502
503 ✗ connect(collisionValidationActivated_, SIGNAL(clicked(bool)),
504 SLOT(activateCollision(bool)));
505 ✗ connect(collisionIndicator_, SIGNAL(mouseClickEvent()),
506 SLOT(requestConfigurationValidation()));
507 ✗ connect(ui_->actionAbout, SIGNAL(triggered()), SLOT(about()));
508 ✗ connect(ui_->actionReconnect, SIGNAL(triggered()), SLOT(resetConnection()));
509 ✗ connect(ui_->actionClose_connections, SIGNAL(triggered()),
510 SLOT(closeConnection()));
511
512 ✗ connect(this, SIGNAL(logString(QString)), SLOT(log(QString)));
513 ✗ connect(this, SIGNAL(logErrorString(QString)), SLOT(logError(QString)));
514
515 ✗ actionSearchBar_->addAction(
516 ✗ new NodeAction(NodeAction::VISIBILITY_ON, "Show node", this));
517 ✗ actionSearchBar_->addAction(
518 ✗ new NodeAction(NodeAction::VISIBILITY_OFF, "Hide node", this));
519 ✗ actionSearchBar_->addAction(
520 ✗ new NodeAction(NodeAction::ALWAYS_ON_TOP, "Always on top", this));
521 ✗ actionSearchBar_->addAction(
522 ✗ new NodeAction(NodeAction::REMOVE_NODE, "Remove node", this));
523 ✗ actionSearchBar_->addAction(ui_->actionFetch_configuration);
524 ✗ actionSearchBar_->addAction(ui_->actionSend_configuration);
525 ✗ actionSearchBar_->addAction(ui_->actionClose_connections);
526 ✗ actionSearchBar_->addAction(ui_->actionReconnect);
527 ✗ actionSearchBar_->addAction(ui_->actionRefresh);
528 }
529
530 ✗ void MainWindow::createCentralWidget() {
531 ✗ if (!osgWindows_.empty()) return;
532 ✗ createDefaultView();
533 }
534
535 ✗ void MainWindow::requestApplyCurrentConfiguration() {
536 ✗ emit applyCurrentConfiguration();
537 ✗ if (collisionValidationActivated_->isChecked())
538 ✗ requestConfigurationValidation();
539 }
540
541 ✗ void MainWindow::requestConfigurationValidation() {
542 ✗ emit configurationValidation();
543 }
544
545 ✗ void MainWindow::onOpenPluginManager() {
546 ✗ PluginManagerDialog d(pluginManager(), this);
547 ✗ d.exec();
548 }
549
550 ✗ void MainWindow::registerSignal(const char* signal, QObject* obj) {
551 ✗ if (registeredSignals_.find(signal) == registeredSignals_.end()) {
552 ✗ registeredSignals_[signal] = obj;
553 ✗ gepetto::log() << signal << " registered" << std::endl;
554 } else
555 ✗ gepetto::log() << "Signal" << signal << "already registered." << std::endl;
556 }
557
558 ✗ QObject* MainWindow::getFromSignal(const char* signal) {
559 ✗ if (registeredSignals_.find(signal) == registeredSignals_.end()) {
560 #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
561 ✗ gepetto::log() << "signal " << signal << "isn't registered" << std::endl;
562 #endif
563 ✗ return NULL;
564 }
565 ✗ return registeredSignals_[signal];
566 }
567
568 ✗ void MainWindow::connectSignal(const char* signal, const char* slot,
569 QObject* obj) {
570 ✗ QObject* obj_sig = getFromSignal(signal);
571 ✗ if (obj_sig != NULL) {
572 ✗ QObject::connect(obj_sig, signal, obj, slot);
573 }
574 }
575
576 ✗ void MainWindow::registerSlot(const char* slot, QObject* obj) {
577 ✗ if (registeredSlots_.find(slot) == registeredSlots_.end()) {
578 ✗ registeredSlots_[slot] = obj;
579 ✗ gepetto::log() << slot << " registered" << std::endl;
580 } else
581 ✗ gepetto::log() << "Slot " << slot << "already registered." << std::endl;
582 }
583
584 ✗ QObject* MainWindow::getFromSlot(const char* slot) {
585 ✗ if (registeredSlots_.find(slot) == registeredSlots_.end()) {
586 ✗ gepetto::log() << "slot" << slot << "isn't registered" << std::endl;
587 ✗ return NULL;
588 }
589 ✗ return registeredSlots_[slot];
590 }
591
592 ✗ void MainWindow::connectSlot(const char* slot, const char* signal,
593 QObject* obj) {
594 ✗ if (registeredSlots_.find(slot) != registeredSlots_.end()) {
595 ✗ QObject::connect(obj, signal, registeredSlots_[slot], slot);
596 }
597 }
598
599 ✗ void MainWindow::registerShortcut(QString widgetName, QString actionName,
600 QAction* action) {
601 ✗ shortcutFactory_->addBinding(widgetName, actionName, action);
602 }
603
604 ✗ void MainWindow::registerShortcut(QString widgetName, QAction* action) {
605 ✗ shortcutFactory_->addBinding(widgetName, action->text(), action);
606 }
607
608 ✗ void MainWindow::configurationValidationStatusChanged(bool valid) {
609 ✗ collisionIndicator_->switchLed(valid);
610 ✗ int state = (valid) ? 0 : 1;
611 ✗ foreach (const QString& s, robotNames_) {
612 ✗ osg()->setHighlight(s.toLocal8Bit().data(), state);
613 }
614 }
615
616 ✗ void MainWindow::configurationValidationStatusChanged(
617 QStringList bodiesInCollision) {
618 ✗ QStringList lastBodiesInCollision = lastBodiesInCollision_;
619 ✗ lastBodiesInCollision_.clear();
620 ✗ collisionIndicator_->switchLed(bodiesInCollision.empty());
621 ✗ foreach (QString b, lastBodiesInCollision) {
622 ✗ if (bodiesInCollision.removeAll(b) == 0) {
623 /// This body is not in collision
624 ✗ osg()->setHighlight(b.toLocal8Bit().data(), 0);
625 } else {
626 /// This body is still in collision
627 ✗ lastBodiesInCollision_.append(b);
628 }
629 }
630 ✗ QString tooltip("Collision between ");
631 ✗ foreach (const QString& b, bodiesInCollision) {
632 ✗ osg()->setHighlight(b.toLocal8Bit().data(), 1);
633 ✗ lastBodiesInCollision_.append(b);
634 }
635 ✗ tooltip += lastBodiesInCollision_.join(", ");
636 ✗ if (lastBodiesInCollision_.count() > 0)
637 ✗ collisionLabel_->setText(tooltip);
638 else
639 ✗ collisionLabel_->setText("No collisions.");
640 }
641
642 ✗ void MainWindow::requestSelectJointFromBodyName(const QString bodyName) {
643 ✗ emit selectJointFromBodyName(bodyName);
644 }
645 } // namespace gui
646 } // namespace gepetto
647