visualization_frame.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <fstream>
31 #include <memory>
32 
33 #include <QAction>
34 #include <QShortcut>
35 #include <QApplication>
36 #include <QCloseEvent>
37 #include <QDesktopServices>
38 #include <QDockWidget>
39 #include <QDir>
40 #include <QFileDialog>
41 #include <QMenu>
42 #include <QMenuBar>
43 #include <QMessageBox>
44 #include <QTimer>
45 #include <QToolBar>
46 #include <QToolButton>
47 #include <QUrl>
48 #include <QStatusBar>
49 #include <QLabel>
50 #include <QToolButton>
51 #include <QHBoxLayout>
52 #include <QTabBar>
53 
54 #include <boost/algorithm/string/split.hpp>
55 #include <boost/algorithm/string/trim.hpp>
56 #include <boost/bind.hpp>
57 #include <boost/filesystem.hpp>
58 
59 #include <ros/console.h>
60 #include <ros/package.h>
61 #include <ros/init.h>
62 
63 #include <OgreRenderWindow.h>
64 #include <OgreMeshManager.h>
65 
67 
68 #include "rviz/displays_panel.h"
69 #include "rviz/env_config.h"
70 #include "rviz/failed_panel.h"
71 #include "rviz/help_panel.h"
72 #include "rviz/loading_dialog.h"
73 #include "rviz/new_object_dialog.h"
74 #include "rviz/preferences.h"
76 #include "rviz/panel_dock_widget.h"
77 #include "rviz/panel_factory.h"
78 #include "rviz/render_panel.h"
79 #include "rviz/screenshot_dialog.h"
81 #include "rviz/selection_panel.h"
82 #include "rviz/splash_screen.h"
83 #include "rviz/time_panel.h"
84 #include "rviz/tool.h"
85 #include "rviz/tool_manager.h"
87 #include "rviz/views_panel.h"
90 #include "rviz/load_resource.h"
93 
95 
96 namespace fs = boost::filesystem;
97 
98 #define CONFIG_EXTENSION "rviz"
99 #define CONFIG_EXTENSION_WILDCARD "*." CONFIG_EXTENSION
100 #define RECENT_CONFIG_COUNT 10
101 
102 #if BOOST_FILESYSTEM_VERSION == 3
103 #define BOOST_FILENAME_STRING filename().string
104 #define BOOST_FILE_STRING string
105 #else
106 #define BOOST_FILENAME_STRING filename
107 #define BOOST_FILE_STRING file_string
108 #endif
109 
110 namespace rviz
111 {
113  : QMainWindow(parent)
114  , app_(nullptr)
115  , render_panel_(nullptr)
116  , show_help_action_(nullptr)
117  , preferences_(new Preferences())
118  , file_menu_(nullptr)
119  , recent_configs_menu_(nullptr)
120  , toolbar_(nullptr)
121  , manager_(nullptr)
122  , splash_(nullptr)
123  , toolbar_actions_(nullptr)
124  , show_choose_new_master_option_(false)
125  , add_tool_action_(nullptr)
126  , remove_tool_menu_(nullptr)
127  , initialized_(false)
128  , geom_change_detector_(new WidgetGeometryChangeDetector(this))
129  , loading_(false)
130  , post_load_timer_(new QTimer(this))
131  , frame_count_(0)
132  , toolbar_visible_(true)
133 {
135 
136  installEventFilter(geom_change_detector_);
137  connect(geom_change_detector_, SIGNAL(changed()), this, SLOT(setDisplayConfigModified()));
138 
139  post_load_timer_->setSingleShot(true);
140  connect(post_load_timer_, SIGNAL(timeout()), this, SLOT(markLoadingDone()));
141 
143  help_path_ = QString::fromStdString((fs::path(package_path_) / "help/help.html").BOOST_FILE_STRING());
144  splash_path_ =
145  QString::fromStdString((fs::path(package_path_) / "images/splash.png").BOOST_FILE_STRING());
146 
147  QToolButton* reset_button = new QToolButton();
148  reset_button->setText("Reset");
149  reset_button->setContentsMargins(0, 0, 0, 0);
150  statusBar()->addPermanentWidget(reset_button, 0);
151  connect(reset_button, SIGNAL(clicked(bool)), this, SLOT(reset()));
152 
153  status_label_ = new QLabel("");
154  statusBar()->addPermanentWidget(status_label_, 1);
155  connect(this, SIGNAL(statusUpdate(const QString&)), status_label_, SLOT(setText(const QString&)));
156 
157  fps_label_ = new QLabel("");
158  fps_label_->setMinimumWidth(40);
159  fps_label_->setAlignment(Qt::AlignRight);
160  statusBar()->addPermanentWidget(fps_label_, 0);
161  original_status_bar_ = statusBar();
162 
163  setWindowTitle("RViz[*]");
164 }
165 
167 {
168  for (int i = 0; i < custom_panels_.size(); i++)
169  {
170  delete custom_panels_[i].dock;
171  }
172 
173  delete panel_factory_;
174  delete render_panel_;
175  delete manager_;
176 }
177 
178 void VisualizationFrame::setApp(QApplication* app)
179 {
180  app_ = app;
181 }
182 
183 void VisualizationFrame::setStatus(const QString& message)
184 {
185  Q_EMIT statusUpdate(message);
186 }
187 
189 {
190  frame_count_++;
192 
193  if (wall_diff.toSec() > 1.0)
194  {
195  float fps = frame_count_ / wall_diff.toSec();
196  frame_count_ = 0;
198  if (original_status_bar_ == statusBar())
199  {
200  fps_label_->setText(QString::number(int(fps)) + QString(" fps"));
201  }
202  }
203 }
204 
205 void VisualizationFrame::closeEvent(QCloseEvent* event)
206 {
207  if (prepareToExit())
208  {
209  event->accept();
210  }
211  else
212  {
213  event->ignore();
214  }
215 }
216 
217 void VisualizationFrame::leaveEvent(QEvent* /*event*/)
218 {
219  setStatus("");
220 }
221 
223 {
224  Ogre::MeshManager::getSingleton().removeAll();
225  manager_->resetTime();
226 }
227 
229 {
230  if (prepareToExit())
231  {
232  QApplication::exit(255);
233  }
234 }
235 
237 {
239 }
240 
241 void VisualizationFrame::setHelpPath(const QString& help_path)
242 {
243  help_path_ = help_path;
245 }
246 
247 void VisualizationFrame::setSplashPath(const QString& splash_path)
248 {
249  splash_path_ = splash_path;
250 }
251 
252 void VisualizationFrame::initialize(const QString& display_config_file)
253 {
254  initConfigs();
255 
257 
258  QIcon app_icon(
259  QString::fromStdString((fs::path(package_path_) / "icons/package.png").BOOST_FILE_STRING()));
260  setWindowIcon(app_icon);
261 
262  if (splash_path_ != "")
263  {
264  QPixmap splash_image(splash_path_);
265  splash_ = new SplashScreen(splash_image);
266  splash_->show();
267  connect(this, SIGNAL(statusUpdate(const QString&)), splash_, SLOT(showMessage(const QString&)));
268  }
269  Q_EMIT statusUpdate("Initializing");
270 
271  // Periodically process events for the splash screen.
272  // See: http://doc.qt.io/qt-5/qsplashscreen.html#details
273  if (app_)
274  app_->processEvents();
275 
276  if (!ros::isInitialized())
277  {
278  int argc = 0;
279  ros::init(argc, nullptr, "rviz", ros::init_options::AnonymousName);
280  }
281 
282  // Periodically process events for the splash screen.
283  if (app_)
284  app_->processEvents();
285 
286  QWidget* central_widget = new QWidget(this);
287  QHBoxLayout* central_layout = new QHBoxLayout;
288  central_layout->setSpacing(0);
289  central_layout->setMargin(0);
290 
291  render_panel_ = new RenderPanel(central_widget);
292 
293  hide_left_dock_button_ = new QToolButton();
294  hide_left_dock_button_->setContentsMargins(0, 0, 0, 0);
295  hide_left_dock_button_->setArrowType(Qt::LeftArrow);
296  hide_left_dock_button_->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
297  hide_left_dock_button_->setFixedWidth(16);
298  hide_left_dock_button_->setAutoRaise(true);
299  hide_left_dock_button_->setCheckable(true);
300 
301  connect(hide_left_dock_button_, SIGNAL(toggled(bool)), this, SLOT(hideLeftDock(bool)));
302 
303  hide_right_dock_button_ = new QToolButton();
304  hide_right_dock_button_->setContentsMargins(0, 0, 0, 0);
305  hide_right_dock_button_->setArrowType(Qt::RightArrow);
306  hide_right_dock_button_->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
307  hide_right_dock_button_->setFixedWidth(16);
308  hide_right_dock_button_->setAutoRaise(true);
309  hide_right_dock_button_->setCheckable(true);
310 
311  connect(hide_right_dock_button_, SIGNAL(toggled(bool)), this, SLOT(hideRightDock(bool)));
312 
313  central_layout->addWidget(hide_left_dock_button_, 0);
314  central_layout->addWidget(render_panel_, 1);
315  central_layout->addWidget(hide_right_dock_button_, 0);
316 
317  central_widget->setLayout(central_layout);
318 
319  // Periodically process events for the splash screen.
320  if (app_)
321  app_->processEvents();
322 
323  initMenus();
324 
325  // Periodically process events for the splash screen.
326  if (app_)
327  app_->processEvents();
328 
329  initToolbars();
330 
331  // Periodically process events for the splash screen.
332  if (app_)
333  app_->processEvents();
334 
335  setCentralWidget(central_widget);
336 
337  // Periodically process events for the splash screen.
338  if (app_)
339  app_->processEvents();
340 
343  connect(manager_, SIGNAL(escapePressed()), this, SLOT(exitFullScreen()));
344 
345  // Periodically process events for the splash screen.
346  if (app_)
347  app_->processEvents();
348 
350 
351  // Periodically process events for the splash screen.
352  if (app_)
353  app_->processEvents();
354 
355  ToolManager* tool_man = manager_->getToolManager();
356 
357  connect(manager_, SIGNAL(configChanged()), this, SLOT(setDisplayConfigModified()));
358  connect(tool_man, SIGNAL(toolAdded(Tool*)), this, SLOT(addTool(Tool*)));
359  connect(tool_man, SIGNAL(toolRemoved(Tool*)), this, SLOT(removeTool(Tool*)));
360  connect(tool_man, SIGNAL(toolRefreshed(Tool*)), this, SLOT(refreshTool(Tool*)));
361  connect(tool_man, SIGNAL(toolChanged(Tool*)), this, SLOT(indicateToolIsCurrent(Tool*)));
362 
363  manager_->initialize();
364 
365  // Periodically process events for the splash screen.
366  if (app_)
367  app_->processEvents();
368 
369  if (display_config_file != "")
370  {
371  loadDisplayConfig(display_config_file);
372  }
373  else
374  {
375  loadDisplayConfig(QString::fromStdString(default_display_config_file_));
376  }
377 
378  // Periodically process events for the splash screen.
379  if (app_)
380  app_->processEvents();
381 
382  delete splash_;
383  splash_ = nullptr;
384 
386  initialized_ = true;
387  Q_EMIT statusUpdate("RViz is ready.");
388 
389  connect(manager_, SIGNAL(preUpdate()), this, SLOT(updateFps()));
390  connect(manager_, SIGNAL(statusUpdate(const QString&)), this, SIGNAL(statusUpdate(const QString&)));
391 }
392 
394 {
395  home_dir_ = QDir::toNativeSeparators(QDir::homePath()).toStdString();
396 
397  config_dir_ = (fs::path(home_dir_) / ".rviz").BOOST_FILE_STRING();
398  persistent_settings_file_ = (fs::path(config_dir_) / "persistent_settings").BOOST_FILE_STRING();
400  (fs::path(config_dir_) / "default." CONFIG_EXTENSION).BOOST_FILE_STRING();
401 
402  if (fs::is_regular_file(config_dir_))
403  {
404  ROS_ERROR("Moving file [%s] out of the way to recreate it as a directory.", config_dir_.c_str());
405  std::string backup_file = config_dir_ + ".bak";
406 
407  fs::rename(config_dir_, backup_file);
408  fs::create_directory(config_dir_);
409  }
410  else if (!fs::exists(config_dir_))
411  {
412  fs::create_directory(config_dir_);
413  }
414 }
415 
417 {
418  YamlConfigReader reader;
419  Config config;
420  reader.readFile(config, QString::fromStdString(persistent_settings_file_));
421  if (!reader.error())
422  {
423  QString last_config_dir, last_image_dir;
424  if (config.mapGetString("Last Config Dir", &last_config_dir) &&
425  config.mapGetString("Last Image Dir", &last_image_dir))
426  {
427  last_config_dir_ = last_config_dir.toStdString();
428  last_image_dir_ = last_image_dir.toStdString();
429  }
430 
431  Config recent_configs_list = config.mapGetChild("Recent Configs");
432  recent_configs_.clear();
433  int num_recent = recent_configs_list.listLength();
434  for (int i = 0; i < num_recent; i++)
435  {
436  recent_configs_.push_back(recent_configs_list.listChildAt(i).getValue().toString().toStdString());
437  }
438  }
439  else
440  {
441  ROS_ERROR("%s", qPrintable(reader.errorMessage()));
442  }
443 }
444 
446 {
447  Config config;
448  config.mapSetValue("Last Config Dir", QString::fromStdString(last_config_dir_));
449  config.mapSetValue("Last Image Dir", QString::fromStdString(last_image_dir_));
450  Config recent_configs_list = config.mapMakeChild("Recent Configs");
451  for (D_string::iterator it = recent_configs_.begin(); it != recent_configs_.end(); ++it)
452  {
453  recent_configs_list.listAppendNew().setValue(QString::fromStdString(*it));
454  }
455 
456  YamlConfigWriter writer;
457  writer.writeFile(config, QString::fromStdString(persistent_settings_file_));
458 
459  if (writer.error())
460  {
461  ROS_ERROR("%s", qPrintable(writer.errorMessage()));
462  }
463 }
464 
466 {
467  file_menu_ = menuBar()->addMenu("&File");
468 
469  QAction* file_menu_open_action =
470  file_menu_->addAction("&Open Config", this, SLOT(onOpen()), QKeySequence("Ctrl+O"));
471  this->addAction(file_menu_open_action);
472  QAction* file_menu_save_action =
473  file_menu_->addAction("&Save Config", this, SLOT(onSave()), QKeySequence("Ctrl+S"));
474  this->addAction(file_menu_save_action);
475  QAction* file_menu_save_as_action =
476  file_menu_->addAction("Save Config &As", this, SLOT(onSaveAs()), QKeySequence("Ctrl+Shift+S"));
477  this->addAction(file_menu_save_as_action);
478 
479  recent_configs_menu_ = file_menu_->addMenu("&Recent Configs");
480  file_menu_->addAction("Save &Image", this, SLOT(onSaveImage()));
482  {
483  file_menu_->addSeparator();
484  file_menu_->addAction("Change &Master", this, SLOT(changeMaster()));
485  }
486  file_menu_->addSeparator();
487  file_menu_->addAction("&Preferences", this, SLOT(openPreferencesDialog()), QKeySequence("Ctrl+P"));
488 
489  QAction* file_menu_quit_action =
490  file_menu_->addAction("&Quit", this, SLOT(close()), QKeySequence("Ctrl+Q"));
491  file_menu_quit_action->setObjectName("actQuit");
492  this->addAction(file_menu_quit_action);
493 
494  view_menu_ = menuBar()->addMenu("&Panels");
495  view_menu_->addAction("Add &New Panel", this, SLOT(openNewPanelDialog()));
496  delete_view_menu_ = view_menu_->addMenu("&Delete Panel");
497  delete_view_menu_->setEnabled(false);
498 
499  QAction* fullscreen_action =
500  view_menu_->addAction("&Fullscreen", this, SLOT(setFullScreen(bool)), Qt::Key_F11);
501  fullscreen_action->setCheckable(true);
502  this->addAction(
503  fullscreen_action); // Also add to window, or the shortcut doest work when the menu is hidden.
504  connect(this, SIGNAL(fullScreenChange(bool)), fullscreen_action, SLOT(setChecked(bool)));
505  view_menu_->addSeparator();
506 
507  QMenu* help_menu = menuBar()->addMenu("&Help");
508  help_menu->addAction("Show &Help panel", this, SLOT(showHelpPanel()));
509  help_menu->addAction("Open rviz wiki in browser", this, SLOT(onHelpWiki()));
510  help_menu->addSeparator();
511  help_menu->addAction("&About", this, SLOT(onHelpAbout()));
512 }
513 
515 {
516  QFont font;
517  font.setPointSize(font.pointSizeF() * 0.9);
518 
519  // make toolbar with plugin tools
520 
521  toolbar_ = addToolBar("Tools");
522  toolbar_->setFont(font);
523  toolbar_->setContentsMargins(0, 0, 0, 0);
524  toolbar_->setObjectName("Tools");
525  toolbar_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
526  toolbar_actions_ = new QActionGroup(this);
527  connect(toolbar_actions_, SIGNAL(triggered(QAction*)), this, SLOT(onToolbarActionTriggered(QAction*)));
528  view_menu_->addAction(toolbar_->toggleViewAction());
529 
530  add_tool_action_ = toolbar_->addSeparator();
531 
532  QToolButton* add_tool_button = new QToolButton();
533  add_tool_button->setToolTip("Add a new tool");
534  add_tool_button->setIcon(loadPixmap("package://rviz/icons/plus.png"));
535  toolbar_->addWidget(add_tool_button);
536  connect(add_tool_button, SIGNAL(clicked()), this, SLOT(openNewToolDialog()));
537 
538  remove_tool_menu_ = new QMenu(toolbar_);
539  QToolButton* remove_tool_button = new QToolButton();
540  remove_tool_button->setMenu(remove_tool_menu_);
541  remove_tool_button->setPopupMode(QToolButton::InstantPopup);
542  remove_tool_button->setToolTip("Remove a tool from the toolbar");
543  remove_tool_button->setIcon(loadPixmap("package://rviz/icons/minus.png"));
544  toolbar_->addWidget(remove_tool_button);
545  connect(remove_tool_menu_, SIGNAL(triggered(QAction*)), this, SLOT(onToolbarRemoveTool(QAction*)));
546 
547  QMenu* button_style_menu = new QMenu(toolbar_);
548  QAction* action_tool_button_icon_only = new QAction("Icon only", toolbar_actions_);
549  action_tool_button_icon_only->setData(Qt::ToolButtonIconOnly);
550  button_style_menu->addAction(action_tool_button_icon_only);
551  QAction* action_tool_button_text_only = new QAction("Text only", toolbar_actions_);
552  action_tool_button_text_only->setData(Qt::ToolButtonTextOnly);
553  button_style_menu->addAction(action_tool_button_text_only);
554  QAction* action_tool_button_text_beside_icon = new QAction("Text beside icon", toolbar_actions_);
555  action_tool_button_text_beside_icon->setData(Qt::ToolButtonTextBesideIcon);
556  button_style_menu->addAction(action_tool_button_text_beside_icon);
557  QAction* action_tool_button_text_under_icon = new QAction("Text under icon", toolbar_actions_);
558  action_tool_button_text_under_icon->setData(Qt::ToolButtonTextUnderIcon);
559  button_style_menu->addAction(action_tool_button_text_under_icon);
560 
561  QToolButton* button_style_button = new QToolButton();
562  button_style_button->setMenu(button_style_menu);
563  button_style_button->setPopupMode(QToolButton::InstantPopup);
564  button_style_button->setToolTip("Set toolbar style");
565  button_style_button->setIcon(loadPixmap("package://rviz/icons/visibility.svg"));
566  toolbar_->addWidget(button_style_button);
567  connect(button_style_menu, SIGNAL(triggered(QAction*)), this, SLOT(onButtonStyleTool(QAction*)));
568 }
569 
570 void VisualizationFrame::hideDockImpl(Qt::DockWidgetArea area, bool hide)
571 {
572  QList<PanelDockWidget*> dock_widgets = findChildren<PanelDockWidget*>();
573 
574  for (QList<PanelDockWidget*>::iterator it = dock_widgets.begin(); it != dock_widgets.end(); it++)
575  {
576  Qt::DockWidgetArea curr_area = dockWidgetArea(*it);
577  if (area == curr_area)
578  {
579  (*it)->setCollapsed(hide);
580  }
581  // allow/disallow docking to this area for all widgets
582  if (hide)
583  {
584  (*it)->setAllowedAreas((*it)->allowedAreas() & ~area);
585  }
586  else
587  {
588  (*it)->setAllowedAreas((*it)->allowedAreas() | area);
589  }
590  }
591 }
592 
594 {
595  hide_left_dock_button_->setVisible(visible);
596  hide_right_dock_button_->setVisible(visible);
597 }
598 
600 {
601  hideDockImpl(Qt::LeftDockWidgetArea, hide);
602  hide_left_dock_button_->setArrowType(hide ? Qt::RightArrow : Qt::LeftArrow);
603 }
604 
606 {
607  hideDockImpl(Qt::RightDockWidgetArea, hide);
608  hide_right_dock_button_->setArrowType(hide ? Qt::LeftArrow : Qt::RightArrow);
609 }
610 
612 {
613  // if a dock widget becomes visible and is resting inside the
614  // left or right dock area, we want to unhide the whole area
615  if (visible)
616  {
617  QDockWidget* dock_widget = dynamic_cast<QDockWidget*>(sender());
618  if (dock_widget)
619  {
620  Qt::DockWidgetArea area = dockWidgetArea(dock_widget);
621  if (area == Qt::LeftDockWidgetArea)
622  {
623  hide_left_dock_button_->setChecked(false);
624  }
625  if (area == Qt::RightDockWidgetArea)
626  {
627  hide_right_dock_button_->setChecked(false);
628  }
629  }
630  }
631 }
632 
634 {
635  Preferences temp_preferences(*preferences_);
636  PreferencesDialog dialog(panel_factory_, &temp_preferences, this);
637  manager_->stopUpdate();
638  if (dialog.exec() == QDialog::Accepted)
639  {
640  // Apply preferences.
641  preferences_ = boost::make_shared<Preferences>(temp_preferences);
642  }
644 }
645 
647 {
648  QString class_id;
649  QString display_name;
650  QStringList empty;
651 
652  NewObjectDialog* dialog =
653  new NewObjectDialog(panel_factory_, "Panel", empty, empty, &class_id, &display_name, this);
654  manager_->stopUpdate();
655  if (dialog->exec() == QDialog::Accepted)
656  {
657  QDockWidget* dock = addPanelByName(display_name, class_id);
658  if (dock)
659  {
660  connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(onDockPanelChange()));
661  }
662  }
664 }
665 
667 {
668  QString class_id;
669  QStringList empty;
670  ToolManager* tool_man = manager_->getToolManager();
671 
672  NewObjectDialog* dialog =
673  new NewObjectDialog(tool_man->getFactory(), "Tool", empty, tool_man->getToolClasses(), &class_id);
674  manager_->stopUpdate();
675  if (dialog->exec() == QDialog::Accepted)
676  {
677  tool_man->addTool(class_id);
678  }
680  activateWindow(); // Force keyboard focus back on main window.
681 }
682 
684 {
685  recent_configs_menu_->clear();
686 
687  D_string::iterator it = recent_configs_.begin();
688  D_string::iterator end = recent_configs_.end();
689  for (; it != end; ++it)
690  {
691  if (!it->empty())
692  {
693  std::string display_name = *it;
694  if (display_name == default_display_config_file_)
695  {
696  display_name += " (default)";
697  }
698  if (display_name.find(home_dir_) == 0)
699  {
700  display_name = ("~" / fs::path(display_name.substr(home_dir_.size()))).BOOST_FILE_STRING();
701  }
702  QString qdisplay_name = QString::fromStdString(display_name);
703  QAction* action = new QAction(qdisplay_name, this);
704  action->setData(QString::fromStdString(*it));
705  connect(action, SIGNAL(triggered()), this, SLOT(onRecentConfigSelected()));
706  recent_configs_menu_->addAction(action);
707  }
708  }
709 }
710 
711 void VisualizationFrame::markRecentConfig(const std::string& path)
712 {
713  D_string::iterator it = std::find(recent_configs_.begin(), recent_configs_.end(), path);
714  if (it != recent_configs_.end())
715  {
716  recent_configs_.erase(it);
717  }
718 
719  recent_configs_.push_front(path);
720 
722  {
723  recent_configs_.pop_back();
724  }
725 
727 }
728 
729 void VisualizationFrame::loadDisplayConfig(const QString& qpath)
730 {
731  std::string path = qpath.toStdString();
732  fs::path actual_load_path = path;
733  bool valid_load_path = fs::is_regular_file(actual_load_path);
734 
735  if (!valid_load_path && fs::portable_posix_name(path))
736  {
737  if (actual_load_path.extension() != "." CONFIG_EXTENSION)
738  actual_load_path += "." CONFIG_EXTENSION;
739  actual_load_path = fs::path(config_dir_) / actual_load_path;
740  if ((valid_load_path = fs::is_regular_file(actual_load_path)))
741  path = actual_load_path.string();
742  }
743 
744  if (!valid_load_path)
745  {
746  actual_load_path = (fs::path(package_path_) / "default.rviz");
747  if (!(valid_load_path = fs::is_regular_file(actual_load_path)))
748  {
749  ROS_ERROR("Default display config '%s' not found. RViz will be very empty at first.",
750  actual_load_path.c_str());
751  return;
752  }
753  }
754  loadDisplayConfigHelper(actual_load_path.BOOST_FILE_STRING());
755 }
756 
757 bool VisualizationFrame::loadDisplayConfigHelper(const std::string& full_path)
758 {
759  // Check if we have unsaved changes to the current config the same
760  // as we do during exit, with the same option to cancel.
761  if (!prepareToExit())
762  {
763  return false;
764  }
765 
766  setWindowModified(false);
767  loading_ = true;
768 
769  std::unique_ptr<LoadingDialog> dialog;
770  if (initialized_)
771  {
772  dialog.reset(new LoadingDialog(this));
773  dialog->show();
774  connect(this, SIGNAL(statusUpdate(const QString&)), dialog.get(), SLOT(showMessage(const QString&)));
775  app_->processEvents(); // make the window correctly appear although running a long-term function
776  }
777 
778  YamlConfigReader reader;
779  Config config;
780  reader.readFile(config, QString::fromStdString(full_path));
781  if (reader.error())
782  return false;
783 
784  load(config);
785 
786  markRecentConfig(full_path);
787 
788  setDisplayConfigFile(full_path);
789 
790  last_config_dir_ = fs::path(full_path).parent_path().BOOST_FILE_STRING();
791 
792  post_load_timer_->start(1000);
793 
794  return true;
795 }
796 
798 {
799  loading_ = false;
800 }
801 
802 void VisualizationFrame::setImageSaveDirectory(const QString& directory)
803 {
804  last_image_dir_ = directory.toStdString();
805 }
806 
808 {
809  if (!loading_)
810  {
811  if (!isWindowModified())
812  {
813  setWindowModified(true);
814  }
815  }
816 }
817 
818 void VisualizationFrame::setDisplayConfigFile(const std::string& path)
819 {
820  display_config_file_ = path;
821 
822  std::string title;
823  if (path == default_display_config_file_)
824  {
825  title = "RViz[*]";
826  }
827  else
828  {
829  title = fs::path(path).BOOST_FILENAME_STRING() + "[*] - RViz";
830  }
831  setWindowTitle(QString::fromStdString(title));
832  Q_EMIT displayConfigFileChanged(QString::fromStdString(path));
833 }
834 
835 bool VisualizationFrame::saveDisplayConfig(const QString& path)
836 {
837  Config config;
838  save(config);
839 
840  YamlConfigWriter writer;
841  writer.writeFile(config, path);
842 
843  if (writer.error())
844  {
845  ROS_ERROR("%s", qPrintable(writer.errorMessage()));
846  error_message_ = writer.errorMessage();
847  return false;
848  }
849  else
850  {
851  setWindowModified(false);
852  error_message_ = "";
853  return true;
854  }
855 }
856 
858 {
859  manager_->save(config.mapMakeChild("Visualization Manager"));
860  savePanels(config.mapMakeChild("Panels"));
861  saveWindowGeometry(config.mapMakeChild("Window Geometry"));
862  savePreferences(config.mapMakeChild("Preferences"));
863  saveToolbars(config.mapMakeChild("Toolbars"));
864 }
865 
866 void VisualizationFrame::load(const Config& config)
867 {
868  manager_->load(config.mapGetChild("Visualization Manager"));
869  loadPanels(config.mapGetChild("Panels"));
870  loadWindowGeometry(config.mapGetChild("Window Geometry"));
871  loadPreferences(config.mapGetChild("Preferences"));
872  configureToolbars(config.mapGetChild("Toolbars"));
873 }
874 
876 {
877  int x, y;
878  if (config.mapGetInt("X", &x) && config.mapGetInt("Y", &y))
879  {
880  move(x, y);
881  }
882 
883  int width, height;
884  if (config.mapGetInt("Width", &width) && config.mapGetInt("Height", &height))
885  {
886  resize(width, height);
887  }
888 
889  QString main_window_config;
890  if (config.mapGetString("QMainWindow State", &main_window_config))
891  {
892  restoreState(QByteArray::fromHex(qPrintable(main_window_config)));
893  }
894 
895  // load panel dock widget states (collapsed or not)
896  QList<PanelDockWidget*> dock_widgets = findChildren<PanelDockWidget*>();
897 
898  for (QList<PanelDockWidget*>::iterator it = dock_widgets.begin(); it != dock_widgets.end(); it++)
899  {
900  Config itConfig = config.mapGetChild((*it)->windowTitle());
901 
902  if (itConfig.isValid())
903  {
904  (*it)->load(itConfig);
905  }
906  }
907 
908  bool b = false;
909  config.mapGetBool("Hide Left Dock", &b);
910  hide_left_dock_button_->setChecked(b);
911  hideLeftDock(b);
912  config.mapGetBool("Hide Right Dock", &b);
913  hideRightDock(b);
914  hide_right_dock_button_->setChecked(b);
915 }
916 
918 {
919  int tool_button_style;
920  if (config.mapGetInt("toolButtonStyle", &tool_button_style))
921  {
922  toolbar_->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(tool_button_style));
923  }
924 }
925 
927 {
928  config.mapSetValue("toolButtonStyle", static_cast<int>(toolbar_->toolButtonStyle()));
929 }
930 
932 {
933  config.mapSetValue("X", x());
934  config.mapSetValue("Y", y());
935  config.mapSetValue("Width", width());
936  config.mapSetValue("Height", height());
937 
938  QByteArray window_state = saveState().toHex();
939  config.mapSetValue("QMainWindow State", window_state.constData());
940 
941  config.mapSetValue("Hide Left Dock", hide_left_dock_button_->isChecked());
942  config.mapSetValue("Hide Right Dock", hide_right_dock_button_->isChecked());
943 
944  // save panel dock widget states (collapsed or not)
945  QList<PanelDockWidget*> dock_widgets = findChildren<PanelDockWidget*>();
946 
947  for (QList<PanelDockWidget*>::iterator it = dock_widgets.begin(); it != dock_widgets.end(); it++)
948  {
949  (*it)->save(config.mapMakeChild((*it)->windowTitle()));
950  }
951 }
952 
954 {
955  // First destroy any existing custom panels.
956  for (int i = 0; i < custom_panels_.size(); i++)
957  {
958  delete custom_panels_[i].dock;
959  delete custom_panels_[i].delete_action;
960  }
961  custom_panels_.clear();
962 
963  // Then load the ones in the config.
964  int num_custom_panels = config.listLength();
965  for (int i = 0; i < num_custom_panels; i++)
966  {
967  Config panel_config = config.listChildAt(i);
968 
969  QString class_id, name;
970  if (panel_config.mapGetString("Class", &class_id) && panel_config.mapGetString("Name", &name))
971  {
972  QDockWidget* dock = addPanelByName(name, class_id);
973  // This is kind of ridiculous - should just be something like
974  // createPanel() and addPanel() so I can do load() without this
975  // qobject_cast.
976  if (dock)
977  {
978  connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(onDockPanelChange()));
979  Panel* panel = qobject_cast<Panel*>(dock->widget());
980  if (panel)
981  {
982  panel->load(panel_config);
983  }
984  }
985  }
986  }
987 
989 }
990 
992 {
993  config.setType(Config::List); // Not really necessary, but gives an empty list if there are no entries,
994  // instead of an Empty config node.
995 
996  for (int i = 0; i < custom_panels_.size(); i++)
997  {
998  custom_panels_[i].panel->save(config.listAppendNew());
999  }
1000 }
1001 
1003 {
1004  config.mapGetBool("PromptSaveOnExit", &(preferences_->prompt_save_on_exit));
1005 }
1006 
1008 {
1009  config.mapSetValue("PromptSaveOnExit", preferences_->prompt_save_on_exit);
1010 }
1011 
1013 {
1014  if (!initialized_)
1015  {
1016  return true;
1017  }
1018 
1020 
1021  if (isWindowModified() && preferences_->prompt_save_on_exit)
1022  {
1023  QMessageBox box(this);
1024  box.setText("There are unsaved changes.");
1025  box.setInformativeText(QString::fromStdString("Save changes to " + display_config_file_ + "?"));
1026  box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1027  box.setDefaultButton(QMessageBox::Save);
1028  manager_->stopUpdate();
1029  int result = box.exec();
1030  manager_->startUpdate();
1031  switch (result)
1032  {
1033  case QMessageBox::Save:
1034  if (saveDisplayConfig(QString::fromStdString(display_config_file_)))
1035  {
1036  return true;
1037  }
1038  else
1039  {
1040  QMessageBox box(this);
1041  box.setWindowTitle("Failed to save.");
1042  box.setText(getErrorMessage());
1043  box.setInformativeText(
1044  QString::fromStdString("Save copy of " + display_config_file_ + " to another file?"));
1045  box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1046  box.setDefaultButton(QMessageBox::Save);
1047  int result = box.exec();
1048  switch (result)
1049  {
1050  case QMessageBox::Save:
1051  onSaveAs();
1052  return true;
1053  case QMessageBox::Discard:
1054  return true;
1055  default:
1056  return false;
1057  }
1058  }
1059  case QMessageBox::Discard:
1060  return true;
1061  default:
1062  return false;
1063  }
1064  }
1065  else
1066  {
1067  return true;
1068  }
1069 }
1070 
1072 {
1073  manager_->stopUpdate();
1074  QString filename = QFileDialog::getOpenFileName(this, "Choose a file to open",
1075  QString::fromStdString(last_config_dir_),
1076  "RViz config files (" CONFIG_EXTENSION_WILDCARD ")");
1077  manager_->startUpdate();
1078 
1079  if (!filename.isEmpty())
1080  {
1081  std::string path = filename.toStdString();
1082 
1083  if (!fs::exists(path))
1084  {
1085  QString message = filename + " does not exist!";
1086  QMessageBox::critical(this, "Config file does not exist", message);
1087  return;
1088  }
1089 
1090  loadDisplayConfig(filename);
1091  }
1092 }
1093 
1095 {
1096  if (!initialized_)
1097  {
1098  return;
1099  }
1100 
1102 
1103  if (!saveDisplayConfig(QString::fromStdString(display_config_file_)))
1104  {
1105  manager_->stopUpdate();
1106  QMessageBox box(this);
1107  box.setWindowTitle("Failed to save.");
1108  box.setText(getErrorMessage());
1109  box.setInformativeText(
1110  QString::fromStdString("Save copy of " + display_config_file_ + " to another file?"));
1111  box.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
1112  box.setDefaultButton(QMessageBox::Save);
1113  if (box.exec() == QMessageBox::Save)
1114  {
1115  onSaveAs();
1116  }
1117  manager_->startUpdate();
1118  }
1119 }
1120 
1122 {
1123  manager_->stopUpdate();
1124  QString q_filename = QFileDialog::getSaveFileName(this, "Choose a file to save to",
1125  QString::fromStdString(last_config_dir_),
1126  "RViz config files (" CONFIG_EXTENSION_WILDCARD ")");
1127  manager_->startUpdate();
1128 
1129  if (!q_filename.isEmpty())
1130  {
1131  std::string filename = q_filename.toStdString();
1132  fs::path path(filename);
1133  if (path.extension() != "." CONFIG_EXTENSION)
1134  {
1135  filename += "." CONFIG_EXTENSION;
1136  }
1137 
1138  if (!saveDisplayConfig(QString::fromStdString(filename)))
1139  {
1140  QMessageBox::critical(this, "Failed to save.", getErrorMessage());
1141  }
1142 
1143  markRecentConfig(filename);
1144  last_config_dir_ = fs::path(filename).parent_path().BOOST_FILE_STRING();
1145  setDisplayConfigFile(filename);
1146  }
1147 }
1148 
1150 {
1151  ScreenshotDialog* dialog =
1152  new ScreenshotDialog(this, render_panel_, QString::fromStdString(last_image_dir_));
1153  connect(dialog, SIGNAL(savedInDirectory(const QString&)), this,
1154  SLOT(setImageSaveDirectory(const QString&)));
1155  dialog->show();
1156 }
1157 
1159 {
1160  QAction* action = dynamic_cast<QAction*>(sender());
1161  if (action)
1162  {
1163  std::string path = action->data().toString().toStdString();
1164  if (!path.empty())
1165  {
1166  if (!fs::exists(path))
1167  {
1168  QString message = QString::fromStdString(path) + " does not exist!";
1169  QMessageBox::critical(this, "Config file does not exist", message);
1170  return;
1171  }
1172 
1173  loadDisplayConfig(QString::fromStdString(path));
1174  }
1175  }
1176 }
1177 
1179 {
1180  QAction* action = new QAction(tool->getName(), toolbar_actions_);
1181  action->setIcon(tool->getIcon());
1182  action->setIconText(tool->getName());
1183  action->setCheckable(true);
1184  toolbar_->insertAction(add_tool_action_, action);
1185  action_to_tool_map_[action] = tool;
1186  tool_to_action_map_[tool] = action;
1187 
1188  remove_tool_menu_->addAction(tool->getName());
1189 
1190  QObject::connect(tool, &Tool::nameChanged, this, &VisualizationFrame::onToolNameChanged);
1191 }
1192 
1193 void VisualizationFrame::onToolNameChanged(const QString& name)
1194 {
1195  // Early return if the tool is not present
1196  auto it = tool_to_action_map_.find(qobject_cast<Tool*>(sender()));
1197  if (it == tool_to_action_map_.end())
1198  return;
1199 
1200  // Change the name of the action
1201  it->second->setIconText(name);
1202 }
1203 
1205 {
1206  Tool* tool = action_to_tool_map_[action];
1207 
1208  if (tool)
1209  {
1211  }
1212 }
1213 
1214 void VisualizationFrame::onToolbarRemoveTool(QAction* remove_tool_menu_action)
1215 {
1216  QString name = remove_tool_menu_action->text();
1217  for (int i = 0; i < manager_->getToolManager()->numTools(); i++)
1218  {
1219  Tool* tool = manager_->getToolManager()->getTool(i);
1220  if (tool->getName() == name)
1221  {
1223  return;
1224  }
1225  }
1226 }
1227 
1228 void VisualizationFrame::onButtonStyleTool(QAction* button_style_tool_menu_action)
1229 {
1230  toolbar_->setToolButtonStyle(
1231  static_cast<Qt::ToolButtonStyle>(button_style_tool_menu_action->data().toInt()));
1232 }
1233 
1235 {
1236  QAction* action = tool_to_action_map_[tool];
1237  if (action)
1238  {
1239  toolbar_actions_->removeAction(action);
1240  toolbar_->removeAction(action);
1241  tool_to_action_map_.erase(tool);
1242  action_to_tool_map_.erase(action);
1243  }
1244  QString tool_name = tool->getName();
1245  QList<QAction*> remove_tool_actions = remove_tool_menu_->actions();
1246  for (int i = 0; i < remove_tool_actions.size(); i++)
1247  {
1248  QAction* removal_action = remove_tool_actions.at(i);
1249  if (removal_action->text() == tool_name)
1250  {
1251  remove_tool_menu_->removeAction(removal_action);
1252  break;
1253  }
1254  }
1255 }
1256 
1258 {
1259  QAction* action = tool_to_action_map_[tool];
1260  action->setIcon(tool->getIcon());
1261  action->setIconText(tool->getName());
1262 }
1263 
1265 {
1266  QAction* action = tool_to_action_map_[tool];
1267  if (action)
1268  {
1269  action->setChecked(true);
1270  }
1271 }
1272 
1274 {
1275  if (!show_help_action_)
1276  {
1277  QDockWidget* dock = addPanelByName("Help", "rviz/Help");
1278  show_help_action_ = dock->toggleViewAction();
1279  connect(dock, SIGNAL(destroyed(QObject*)), this, SLOT(onHelpDestroyed()));
1280  }
1281  else
1282  {
1283  // show_help_action_ is a toggle action, so trigger() changes its
1284  // state. Therefore we must force it to the opposite state from
1285  // what we want before we call trigger(). (I think.)
1286  show_help_action_->setChecked(false);
1287  show_help_action_->trigger();
1288  }
1289 }
1290 
1292 {
1293  show_help_action_ = nullptr;
1294 }
1295 
1297 {
1298  QDesktopServices::openUrl(QUrl("http://wiki.ros.org/rviz"));
1299 }
1300 
1302 {
1303  QString about_text = QString("This is RViz version %1 (%2).\n"
1304  "\n"
1305  "Compiled against Qt version %3."
1306  "\n"
1307  "Compiled against OGRE version %4.%5.%6%7 (%8).")
1308  .arg(get_version().c_str())
1309  .arg(get_distro().c_str())
1310  .arg(QT_VERSION_STR)
1311  .arg(OGRE_VERSION_MAJOR)
1312  .arg(OGRE_VERSION_MINOR)
1313  .arg(OGRE_VERSION_PATCH)
1314  .arg(OGRE_VERSION_SUFFIX)
1315  .arg(OGRE_VERSION_NAME);
1316 
1317  QMessageBox::about(QApplication::activeWindow(), "About", about_text);
1318 }
1319 
1321 {
1322  QList<QTabBar*> tab_bars = findChildren<QTabBar*>(QString(), Qt::FindDirectChildrenOnly);
1323  for (QList<QTabBar*>::iterator it = tab_bars.begin(); it != tab_bars.end(); it++)
1324  {
1325  (*it)->setElideMode(Qt::ElideNone);
1326  }
1327 }
1328 
1330 {
1331  return this;
1332 }
1333 
1335 {
1336  // This should only be called as a SLOT from a QAction in the
1337  // "delete panel" submenu, so the sender will be one of the QActions
1338  // stored as "delete_action" in a PanelRecord. This code looks for
1339  // a delete_action in custom_panels_ matching sender() and removes
1340  // the panel associated with it.
1341  if (QAction* action = qobject_cast<QAction*>(sender()))
1342  {
1343  for (int i = 0; i < custom_panels_.size(); i++)
1344  {
1345  if (custom_panels_[i].delete_action == action)
1346  {
1347  delete custom_panels_[i].dock;
1348  custom_panels_.removeAt(i);
1350  action->deleteLater();
1351  if (delete_view_menu_->actions().size() == 1 && delete_view_menu_->actions().first() == action)
1352  {
1353  delete_view_menu_->setEnabled(false);
1354  }
1355  return;
1356  }
1357  }
1358  }
1359 }
1360 
1362 {
1363  Qt::WindowStates state = windowState();
1364  if (full_screen == state.testFlag(Qt::WindowFullScreen))
1365  return;
1366  Q_EMIT(fullScreenChange(full_screen));
1367 
1368  // when switching to fullscreen, remember visibility state of toolbar
1369  if (full_screen)
1370  toolbar_visible_ = toolbar_->isVisible();
1371  menuBar()->setVisible(!full_screen);
1372  toolbar_->setVisible(!full_screen && toolbar_visible_);
1373  statusBar()->setVisible(!full_screen);
1374  setHideButtonVisibility(!full_screen);
1375 
1376  if (full_screen)
1377  setWindowState(state | Qt::WindowFullScreen);
1378  else
1379  setWindowState(state & ~Qt::WindowFullScreen);
1380  show();
1381 }
1382 
1384 {
1385  setFullScreen(false);
1386 }
1387 
1388 QDockWidget* VisualizationFrame::addPanelByName(const QString& name,
1389  const QString& class_id,
1390  Qt::DockWidgetArea area,
1391  bool floating)
1392 {
1393  QString error;
1394  Panel* panel = panel_factory_->make(class_id, &error);
1395  if (!panel)
1396  {
1397  panel = new FailedPanel(class_id, error);
1398  }
1399  panel->setName(name);
1400  connect(panel, SIGNAL(configChanged()), this, SLOT(setDisplayConfigModified()));
1401 
1402  PanelRecord record;
1403  record.dock = addPane(name, panel, area, floating);
1404  record.panel = panel;
1405  record.name = name;
1406  record.delete_action = delete_view_menu_->addAction(name, this, SLOT(onDeletePanel()));
1407  custom_panels_.append(record);
1408  delete_view_menu_->setEnabled(true);
1409 
1410  record.panel->initialize(manager_);
1411 
1412  record.dock->setIcon(panel_factory_->getIcon(class_id));
1413 
1414  return record.dock;
1415 }
1416 
1418 VisualizationFrame::addPane(const QString& name, QWidget* panel, Qt::DockWidgetArea area, bool floating)
1419 {
1420  PanelDockWidget* dock;
1421  dock = new PanelDockWidget(name);
1422  addDockWidget(area, dock);
1423 
1424  dock->setContentWidget(panel);
1425  dock->setFloating(floating);
1426  dock->setObjectName(name); // QMainWindow::saveState() needs objectName to be set.
1427 
1428  // we want to know when that panel becomes visible
1429  connect(dock, SIGNAL(visibilityChanged(bool)), this, SLOT(onDockPanelVisibilityChange(bool)));
1430  connect(this, SIGNAL(fullScreenChange(bool)), dock, SLOT(overrideVisibility(bool)));
1431 
1432  QAction* toggle_action = dock->toggleViewAction();
1433  view_menu_->addAction(toggle_action);
1434 
1435  connect(toggle_action, SIGNAL(triggered(bool)), this, SLOT(setDisplayConfigModified()));
1436  connect(dock, SIGNAL(closed()), this, SLOT(setDisplayConfigModified()));
1437 
1438  dock->installEventFilter(geom_change_detector_);
1439 
1440  // repair/update visibility status
1441  hideLeftDock(area == Qt::LeftDockWidgetArea ? false : hide_left_dock_button_->isChecked());
1442  hideRightDock(area == Qt::RightDockWidgetArea ? false : hide_right_dock_button_->isChecked());
1443 
1444  return dock;
1445 }
1446 
1447 } // end namespace rviz
void setContentWidget(QWidget *child)
boost::shared_ptr< Preferences > preferences_
void indicateToolIsCurrent(Tool *tool)
Mark the given tool as the current one.
void addTool(Tool *tool)
Add the given tool to this frame&#39;s toolbar.
void saveToolbars(Config config)
Saves the user configuration of the toolbar to the config node.
void exitFullScreen()
Exit full screen mode.
void setIcon(QIcon icon)
void setHideButtonVisibility(bool visible)
Hide or show the hide-dock buttons.
void initialize()
Do initialization that wasn&#39;t done in constructor. Initializes tool manager, view manager...
void removeTool(Tool *tool)
Remove the given tool from the frame&#39;s toolbar.
filename
void fullScreenChange(bool hidden)
Emitted when the interface enters or leaves full screen mode.
void setValue(const QVariant &value)
Ensures this is a valid Config object, sets the type to Value then sets the value.
Definition: config.cpp:317
PanelDockWidget * addPane(const QString &name, QWidget *panel, Qt::DockWidgetArea area=Qt::LeftDockWidgetArea, bool floating=false) override
bool saveDisplayConfig(const QString &path)
Save display and other settings to the given file.
virtual void load(const Config &config)
Load the properties of all subsystems from the given Config.
QString error_message_
Error message (if any) from most recent saveDisplayConfig() call.
void initialize(Ogre::SceneManager *scene_manager, DisplayContext *manager)
void initialize(VisualizationManager *manager)
Definition: panel.cpp:44
QString errorMessage()
Return an error message if the latest read call had an error, or the empty string if not...
void onDeletePanel()
Delete a panel widget.
void statusUpdate(const QString &message)
Emitted during file-loading and initialization to indicate progress.
QVariant getValue() const
If this config object is valid and is a Value type, this returns its value. Otherwise it returns an i...
Definition: config.cpp:324
void setSplashPath(const QString &splash_path)
Set the path to the "splash" image file. This image is shown during initialization and loading of the...
void removeTool(int index)
QString errorMessage()
Return an error message if the latest write call had an error, or the empty string if there was no er...
ROSCPP_DECL bool isInitialized()
void leaveEvent(QEvent *event) override
void onToolbarRemoveTool(QAction *remove_tool_menu_action)
Remove a the tool whose name is given by remove_tool_menu_action->text().
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
config
int listLength() const
Returns the length of the List in this Node, or 0 if this Node does not have type List...
Definition: config.cpp:329
Config mapGetChild(const QString &key) const
If the referenced Node is a Map and it has a child with the given key, return a reference to the chil...
Definition: config.cpp:212
bool mapGetString(const QString &key, QString *value_out) const
Convenience function for looking up a named string.
Definition: config.cpp:293
Tool * getTool(int index)
Return the tool at a given index in the Tool list. If index is less than 0 or greater than the number...
void initialize(const QString &display_config_file="")
Initialize the visualizer. Creates the VisualizationManager.
Ogre::SceneManager * getSceneManager() const override
Returns the Ogre::SceneManager used for the main RenderPanel.
void displayConfigFileChanged(const QString &fullpath)
Emitted when the config file has changed.
void savePanels(Config config)
Saves custom panels to the given config node.
QWidget * getParentWindow() override
bool toolbar_visible_
Indicates if the toolbar should be visible outside of fullscreen mode.
bool error()
Return true if the latest write operation had an error.
virtual void onDockPanelVisibilityChange(bool visible)
void savePersistentSettings()
Save the "general" config file, which has just the few things which should not be saved with a displa...
bool isValid() const
Returns true if the internal Node reference is valid, false if not. Same as (getType() != Invalid)...
Definition: config.cpp:312
std::map< Tool *, QAction * > tool_to_action_map_
void mapSetValue(const QString &key, QVariant value)
Set a named child to the given value.
Definition: config.cpp:196
void setCurrentTool(Tool *tool)
Set the current tool. The current tool is given all mouse and keyboard events which VisualizationMana...
A dialog for grabbing a screen shot.
Configuration data storage class.
Definition: config.h:124
void setStatus(const QString &message) override
void loadWindowGeometry(const Config &config)
void closeEvent(QCloseEvent *event) override
virtual void setName(const QString &name)
Definition: panel.h:65
void onToolbarActionTriggered(QAction *action)
Looks up the Tool for this action and calls VisualizationManager::setCurrentTool().
VisualizationFrame(QWidget *parent=nullptr)
void readFile(Config &config, const QString &filename)
Read config data from a file. This potentially changes the return value sof error(), statusMessage(), and config().
QList< PanelRecord > custom_panels_
void save(Config config) const
Save the properties of each Display and most editable rviz data.
void setDisplayConfigFile(const std::string &path)
Set the display config file path.
#define CONFIG_EXTENSION
QStringList getToolClasses()
void setImageSaveDirectory(const QString &directory)
Set the default directory in which to save screenshot images.
VisualizationManager * manager_
void setFullScreen(bool full_screen)
Set full screen mode.
Config mapMakeChild(const QString &key)
Create a child node stored with the given key, and return the child.
Definition: config.cpp:201
void loadPersistentSettings()
Load the "general" config file, which has just the few things which should not be saved with a displa...
std::string get_version()
The VisualizationManager class is the central manager class of rviz, holding all the Displays...
void setHelpPath(const QString &help_path)
Set the path to the help file. Should contain HTML. Default is a file in the RViz package...
Tool * addTool(const QString &tool_class_lookup_name)
Create a tool by class lookup name, add it to the list, and return it.
bool error()
Return true if the latest readFile() or readString() call had an error.
void loadPreferences(const Config &config)
#define RECENT_CONFIG_COUNT
void load(const Config &config)
Load the properties of each Display and most editable rviz data.
void initConfigs()
Initialize the default config directory (~/.rviz) and set up the persistent_settings_file_ and displa...
void markLoadingDone()
Set loading_ to false.
std::string get_distro()
ROSLIB_DECL std::string getPath(const std::string &package_name)
action
void savePreferences(Config config)
void onButtonStyleTool(QAction *button_style_tool_menu_action)
Change the button style of the toolbar.
void loadDisplayConfig(const QString &path)
Load display and other settings from the given file.
QDockWidget * addPanelByName(const QString &name, const QString &class_lookup_name, Qt::DockWidgetArea area=Qt::LeftDockWidgetArea, bool floating=false)
void nameChanged(const QString &name)
bool loading_
True just when loading a display config file, false all other times.
void writeFile(const Config &config, const QString &filename)
Write config data to a file. This potentially changes the return values of error() and statusMessage(...
bool loadDisplayConfigHelper(const std::string &full_path)
Load display and other settings from the given full file path.
bool mapGetBool(const QString &key, bool *value_out) const
Convenience function for looking up a named boolean.
Definition: config.cpp:282
const QIcon & getIcon()
Get the icon of this tool.
Definition: tool.h:177
virtual Type * make(const QString &class_id, QString *error_return=nullptr)
Instantiate and return a instance of a subclass of Type using makeRaw().
static WallTime now()
void setDisplayConfigModified()
Call this to let the frame know that something that would get saved in the display config has changed...
void hideDockImpl(Qt::DockWidgetArea area, bool hide)
Config listAppendNew()
Ensure the referenced Node is of type List, append a new Empty Node to the end of the list...
Definition: config.cpp:346
Config listChildAt(int i) const
Return the i&#39;th child in the list, if the referenced Node has type List. Returns an Invalid Config if...
Definition: config.cpp:334
void saveWindowGeometry(Config config)
#define CONFIG_EXTENSION_WILDCARD
PluginlibFactory< Tool > * getFactory()
Definition: tool_manager.h:131
void changeMaster()
Save the current state and quit with exit code 255 to signal the wrapper that we would like to restar...
Utility class for watching for events which indicate that widget geometry has changed.
#define BOOST_FILE_STRING
bool prepareToExit()
Check for unsaved changes, prompt to save config, etc.
WidgetGeometryChangeDetector * geom_change_detector_
void initToolbars()
Sets up the top toolbar with QToolbuttions for adding/deleting tools and modifiying the tool view...
virtual void load(const Config &config)
Override to load configuration data. This version loads the name of the panel.
Definition: panel.cpp:56
void onToolNameChanged(const QString &name)
React to name changes of a tool, updating the name of the associated QAction.
void setApp(QApplication *app)
bool mapGetInt(const QString &key, int *value_out) const
Convenience function for looking up a named integer.
Definition: config.cpp:240
void loadPanels(const Config &config)
Loads custom panels from the given config node.
Dock widget class for docking widgets into VisualizationFrame.
void markRecentConfig(const std::string &path)
ToolManager * getToolManager() const override
Return a pointer to the ToolManager.
void startUpdate()
Start timers. Creates and starts the update and idle timers, both set to 30Hz (33ms).
#define ROS_ERROR(...)
QPixmap loadPixmap(QString url, bool fill_cache)
void setShowChooseNewMaster(bool show)
Call this before initialize() to have it take effect.
virtual void save(Config config)
Save the properties of each subsystem and most editable rviz data.
void resetTime()
Resets the wall and ROS elapsed time to zero and calls resetDisplays().
QIcon getIcon(const QString &class_id) const override
void setType(Type new_type)
Set the type of this Config Node.
Definition: config.cpp:183
std::map< QAction *, Tool * > action_to_tool_map_
void refreshTool(Tool *tool)
Refresh the given tool in this frame&#39;s&#39; toolbar.
QString getName() const
Definition: tool.h:124
virtual void setHelpPath(const QString &help_path)
void configureToolbars(const Config &config)
Applies the user defined toolbar configuration from the given config node.


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sun Jul 3 2022 02:05:32