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 = custom_panels_.size() - 1; i >= 0; --i)
169  delete custom_panels_[i].dock;
170 
171  delete panel_factory_;
172  delete render_panel_;
173  delete manager_;
174 }
175 
176 void VisualizationFrame::setApp(QApplication* app)
177 {
178  app_ = app;
179 }
180 
181 void VisualizationFrame::setStatus(const QString& message)
182 {
183  Q_EMIT statusUpdate(message);
184 }
185 
187 {
188  frame_count_++;
190 
191  if (wall_diff.toSec() > 1.0)
192  {
193  float fps = frame_count_ / wall_diff.toSec();
194  frame_count_ = 0;
196  if (original_status_bar_ == statusBar())
197  {
198  fps_label_->setText(QString::number(int(fps)) + QString(" fps"));
199  }
200  }
201 }
202 
203 void VisualizationFrame::closeEvent(QCloseEvent* event)
204 {
205  if (prepareToExit())
206  {
207  event->accept();
208  }
209  else
210  {
211  event->ignore();
212  }
213 }
214 
215 void VisualizationFrame::leaveEvent(QEvent* /*event*/)
216 {
217  setStatus("");
218 }
219 
221 {
222  Ogre::MeshManager::getSingleton().removeAll();
223  manager_->resetTime();
224 }
225 
227 {
228  if (prepareToExit())
229  {
230  QApplication::exit(255);
231  }
232 }
233 
235 {
237 }
238 
239 void VisualizationFrame::setHelpPath(const QString& help_path)
240 {
241  help_path_ = help_path;
243 }
244 
245 void VisualizationFrame::setSplashPath(const QString& splash_path)
246 {
247  splash_path_ = splash_path;
248 }
249 
250 void VisualizationFrame::initialize(const QString& display_config_file)
251 {
252  initConfigs();
253 
255 
256  QIcon app_icon(
257  QString::fromStdString((fs::path(package_path_) / "icons/package.png").BOOST_FILE_STRING()));
258  setWindowIcon(app_icon);
259 
260  if (splash_path_ != "")
261  {
262  QPixmap splash_image(splash_path_);
263  splash_ = new SplashScreen(splash_image);
264  splash_->show();
265  connect(this, SIGNAL(statusUpdate(const QString&)), splash_, SLOT(showMessage(const QString&)));
266  }
267  Q_EMIT statusUpdate("Initializing");
268 
269  // Periodically process events for the splash screen.
270  // See: http://doc.qt.io/qt-5/qsplashscreen.html#details
271  if (app_)
272  app_->processEvents();
273 
274  if (!ros::isInitialized())
275  {
276  int argc = 0;
277  ros::init(argc, nullptr, "rviz", ros::init_options::AnonymousName);
278  }
279 
280  // Periodically process events for the splash screen.
281  if (app_)
282  app_->processEvents();
283 
284  QWidget* central_widget = new QWidget(this);
285  QHBoxLayout* central_layout = new QHBoxLayout;
286  central_layout->setSpacing(0);
287  central_layout->setMargin(0);
288 
289  render_panel_ = new RenderPanel(central_widget);
290 
291  hide_left_dock_button_ = new QToolButton();
292  hide_left_dock_button_->setContentsMargins(0, 0, 0, 0);
293  hide_left_dock_button_->setArrowType(Qt::LeftArrow);
294  hide_left_dock_button_->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
295  hide_left_dock_button_->setFixedWidth(16);
296  hide_left_dock_button_->setAutoRaise(true);
297  hide_left_dock_button_->setCheckable(true);
298 
299  connect(hide_left_dock_button_, SIGNAL(toggled(bool)), this, SLOT(hideLeftDock(bool)));
300 
301  hide_right_dock_button_ = new QToolButton();
302  hide_right_dock_button_->setContentsMargins(0, 0, 0, 0);
303  hide_right_dock_button_->setArrowType(Qt::RightArrow);
304  hide_right_dock_button_->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
305  hide_right_dock_button_->setFixedWidth(16);
306  hide_right_dock_button_->setAutoRaise(true);
307  hide_right_dock_button_->setCheckable(true);
308 
309  connect(hide_right_dock_button_, SIGNAL(toggled(bool)), this, SLOT(hideRightDock(bool)));
310 
311  central_layout->addWidget(hide_left_dock_button_, 0);
312  central_layout->addWidget(render_panel_, 1);
313  central_layout->addWidget(hide_right_dock_button_, 0);
314 
315  central_widget->setLayout(central_layout);
316 
317  // Periodically process events for the splash screen.
318  if (app_)
319  app_->processEvents();
320 
321  initMenus();
322 
323  // Periodically process events for the splash screen.
324  if (app_)
325  app_->processEvents();
326 
327  initToolbars();
328 
329  // Periodically process events for the splash screen.
330  if (app_)
331  app_->processEvents();
332 
333  setCentralWidget(central_widget);
334 
335  // Periodically process events for the splash screen.
336  if (app_)
337  app_->processEvents();
338 
341  connect(manager_, SIGNAL(escapePressed()), this, SLOT(exitFullScreen()));
342 
343  // Periodically process events for the splash screen.
344  if (app_)
345  app_->processEvents();
346 
348 
349  // Periodically process events for the splash screen.
350  if (app_)
351  app_->processEvents();
352 
353  ToolManager* tool_man = manager_->getToolManager();
354 
355  connect(manager_, SIGNAL(configChanged()), this, SLOT(setDisplayConfigModified()));
356  connect(tool_man, SIGNAL(toolAdded(Tool*)), this, SLOT(addTool(Tool*)));
357  connect(tool_man, SIGNAL(toolRemoved(Tool*)), this, SLOT(removeTool(Tool*)));
358  connect(tool_man, SIGNAL(toolRefreshed(Tool*)), this, SLOT(refreshTool(Tool*)));
359  connect(tool_man, SIGNAL(toolChanged(Tool*)), this, SLOT(indicateToolIsCurrent(Tool*)));
360 
361  manager_->initialize();
362 
363  // Periodically process events for the splash screen.
364  if (app_)
365  app_->processEvents();
366 
367  if (display_config_file != "")
368  {
369  loadDisplayConfig(display_config_file);
370  }
371  else
372  {
373  loadDisplayConfig(QString::fromStdString(default_display_config_file_));
374  }
375 
376  // Periodically process events for the splash screen.
377  if (app_)
378  app_->processEvents();
379 
380  delete splash_;
381  splash_ = nullptr;
382 
384  initialized_ = true;
385  Q_EMIT statusUpdate("RViz is ready.");
386 
387  connect(manager_, SIGNAL(preUpdate()), this, SLOT(updateFps()));
388  connect(manager_, SIGNAL(statusUpdate(const QString&)), this, SIGNAL(statusUpdate(const QString&)));
389 }
390 
392 {
393  home_dir_ = QDir::toNativeSeparators(QDir::homePath()).toStdString();
394 
395  config_dir_ = (fs::path(home_dir_) / ".rviz").BOOST_FILE_STRING();
396  persistent_settings_file_ = (fs::path(config_dir_) / "persistent_settings").BOOST_FILE_STRING();
398  (fs::path(config_dir_) / "default." CONFIG_EXTENSION).BOOST_FILE_STRING();
399 
400  if (fs::is_regular_file(config_dir_))
401  {
402  ROS_ERROR("Moving file [%s] out of the way to recreate it as a directory.", config_dir_.c_str());
403  std::string backup_file = config_dir_ + ".bak";
404 
405  fs::rename(config_dir_, backup_file);
406  fs::create_directory(config_dir_);
407  }
408  else if (!fs::exists(config_dir_))
409  {
410  fs::create_directory(config_dir_);
411  }
412 }
413 
415 {
416  YamlConfigReader reader;
417  Config config;
418  reader.readFile(config, QString::fromStdString(persistent_settings_file_));
419  if (!reader.error())
420  {
421  QString last_config_dir, last_image_dir;
422  if (config.mapGetString("Last Config Dir", &last_config_dir) &&
423  config.mapGetString("Last Image Dir", &last_image_dir))
424  {
425  last_config_dir_ = last_config_dir.toStdString();
426  last_image_dir_ = last_image_dir.toStdString();
427  }
428 
429  Config recent_configs_list = config.mapGetChild("Recent Configs");
430  recent_configs_.clear();
431  int num_recent = recent_configs_list.listLength();
432  for (int i = 0; i < num_recent; i++)
433  {
434  recent_configs_.push_back(recent_configs_list.listChildAt(i).getValue().toString().toStdString());
435  }
436  }
437  else
438  {
439  ROS_ERROR("%s", qPrintable(reader.errorMessage()));
440  }
441 }
442 
444 {
445  Config config;
446  config.mapSetValue("Last Config Dir", QString::fromStdString(last_config_dir_));
447  config.mapSetValue("Last Image Dir", QString::fromStdString(last_image_dir_));
448  Config recent_configs_list = config.mapMakeChild("Recent Configs");
449  for (D_string::iterator it = recent_configs_.begin(); it != recent_configs_.end(); ++it)
450  {
451  recent_configs_list.listAppendNew().setValue(QString::fromStdString(*it));
452  }
453 
454  YamlConfigWriter writer;
455  writer.writeFile(config, QString::fromStdString(persistent_settings_file_));
456 
457  if (writer.error())
458  {
459  ROS_ERROR("%s", qPrintable(writer.errorMessage()));
460  }
461 }
462 
464 {
465  file_menu_ = menuBar()->addMenu("&File");
466 
467  QAction* file_menu_open_action =
468  file_menu_->addAction("&Open Config", this, SLOT(onOpen()), QKeySequence("Ctrl+O"));
469  this->addAction(file_menu_open_action);
470  QAction* file_menu_save_action =
471  file_menu_->addAction("&Save Config", this, SLOT(onSave()), QKeySequence("Ctrl+S"));
472  this->addAction(file_menu_save_action);
473  QAction* file_menu_save_as_action =
474  file_menu_->addAction("Save Config &As", this, SLOT(onSaveAs()), QKeySequence("Ctrl+Shift+S"));
475  this->addAction(file_menu_save_as_action);
476 
477  recent_configs_menu_ = file_menu_->addMenu("&Recent Configs");
478  file_menu_->addAction("Save &Image", this, SLOT(onSaveImage()));
480  {
481  file_menu_->addSeparator();
482  file_menu_->addAction("Change &Master", this, SLOT(changeMaster()));
483  }
484  file_menu_->addSeparator();
485  file_menu_->addAction("&Preferences", this, SLOT(openPreferencesDialog()), QKeySequence("Ctrl+P"));
486 
487  QAction* file_menu_quit_action =
488  file_menu_->addAction("&Quit", this, SLOT(close()), QKeySequence("Ctrl+Q"));
489  file_menu_quit_action->setObjectName("actQuit");
490  this->addAction(file_menu_quit_action);
491 
492  view_menu_ = menuBar()->addMenu("&Panels");
493  view_menu_->addAction("Add &New Panel", this, SLOT(openNewPanelDialog()));
494  delete_view_menu_ = view_menu_->addMenu("&Delete Panel");
495  delete_view_menu_->setEnabled(false);
496 
497  QAction* fullscreen_action =
498  view_menu_->addAction("&Fullscreen", this, SLOT(setFullScreen(bool)), Qt::Key_F11);
499  fullscreen_action->setCheckable(true);
500  this->addAction(
501  fullscreen_action); // Also add to window, or the shortcut doest work when the menu is hidden.
502  connect(this, SIGNAL(fullScreenChange(bool)), fullscreen_action, SLOT(setChecked(bool)));
503  view_menu_->addSeparator();
504 
505  QMenu* help_menu = menuBar()->addMenu("&Help");
506  help_menu->addAction("Show &Help panel", this, SLOT(showHelpPanel()));
507  help_menu->addAction("Open rviz wiki in browser", this, SLOT(onHelpWiki()));
508  help_menu->addSeparator();
509  help_menu->addAction("&About", this, SLOT(onHelpAbout()));
510 }
511 
513 {
514  QFont font;
515  font.setPointSize(font.pointSizeF() * 0.9);
516 
517  // make toolbar with plugin tools
518 
519  toolbar_ = addToolBar("Tools");
520  toolbar_->setFont(font);
521  toolbar_->setContentsMargins(0, 0, 0, 0);
522  toolbar_->setObjectName("Tools");
523  toolbar_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
524  toolbar_actions_ = new QActionGroup(this);
525  connect(toolbar_actions_, SIGNAL(triggered(QAction*)), this, SLOT(onToolbarActionTriggered(QAction*)));
526  view_menu_->addAction(toolbar_->toggleViewAction());
527 
528  add_tool_action_ = toolbar_->addSeparator();
529 
530  QToolButton* add_tool_button = new QToolButton();
531  add_tool_button->setToolTip("Add a new tool");
532  add_tool_button->setIcon(loadPixmap("package://rviz/icons/plus.png"));
533  toolbar_->addWidget(add_tool_button);
534  connect(add_tool_button, SIGNAL(clicked()), this, SLOT(openNewToolDialog()));
535 
536  remove_tool_menu_ = new QMenu(toolbar_);
537  QToolButton* remove_tool_button = new QToolButton();
538  remove_tool_button->setMenu(remove_tool_menu_);
539  remove_tool_button->setPopupMode(QToolButton::InstantPopup);
540  remove_tool_button->setToolTip("Remove a tool from the toolbar");
541  remove_tool_button->setIcon(loadPixmap("package://rviz/icons/minus.png"));
542  toolbar_->addWidget(remove_tool_button);
543  connect(remove_tool_menu_, SIGNAL(triggered(QAction*)), this, SLOT(onToolbarRemoveTool(QAction*)));
544 
545  QMenu* button_style_menu = new QMenu(toolbar_);
546  QAction* action_tool_button_icon_only = new QAction("Icon only", toolbar_actions_);
547  action_tool_button_icon_only->setData(Qt::ToolButtonIconOnly);
548  button_style_menu->addAction(action_tool_button_icon_only);
549  QAction* action_tool_button_text_only = new QAction("Text only", toolbar_actions_);
550  action_tool_button_text_only->setData(Qt::ToolButtonTextOnly);
551  button_style_menu->addAction(action_tool_button_text_only);
552  QAction* action_tool_button_text_beside_icon = new QAction("Text beside icon", toolbar_actions_);
553  action_tool_button_text_beside_icon->setData(Qt::ToolButtonTextBesideIcon);
554  button_style_menu->addAction(action_tool_button_text_beside_icon);
555  QAction* action_tool_button_text_under_icon = new QAction("Text under icon", toolbar_actions_);
556  action_tool_button_text_under_icon->setData(Qt::ToolButtonTextUnderIcon);
557  button_style_menu->addAction(action_tool_button_text_under_icon);
558 
559  QToolButton* button_style_button = new QToolButton();
560  button_style_button->setMenu(button_style_menu);
561  button_style_button->setPopupMode(QToolButton::InstantPopup);
562  button_style_button->setToolTip("Set toolbar style");
563  button_style_button->setIcon(loadPixmap("package://rviz/icons/visibility.svg"));
564  toolbar_->addWidget(button_style_button);
565  connect(button_style_menu, SIGNAL(triggered(QAction*)), this, SLOT(onButtonStyleTool(QAction*)));
566 }
567 
568 void VisualizationFrame::hideDockImpl(Qt::DockWidgetArea area, bool hide)
569 {
570  QList<PanelDockWidget*> dock_widgets = findChildren<PanelDockWidget*>();
571 
572  for (QList<PanelDockWidget*>::iterator it = dock_widgets.begin(); it != dock_widgets.end(); it++)
573  {
574  Qt::DockWidgetArea curr_area = dockWidgetArea(*it);
575  if (area == curr_area)
576  {
577  (*it)->setCollapsed(hide);
578  }
579  // allow/disallow docking to this area for all widgets
580  if (hide)
581  {
582  (*it)->setAllowedAreas((*it)->allowedAreas() & ~area);
583  }
584  else
585  {
586  (*it)->setAllowedAreas((*it)->allowedAreas() | area);
587  }
588  }
589 }
590 
592 {
593  hide_left_dock_button_->setVisible(visible);
594  hide_right_dock_button_->setVisible(visible);
595 }
596 
598 {
599  hideDockImpl(Qt::LeftDockWidgetArea, hide);
600  hide_left_dock_button_->setArrowType(hide ? Qt::RightArrow : Qt::LeftArrow);
601 }
602 
604 {
605  hideDockImpl(Qt::RightDockWidgetArea, hide);
606  hide_right_dock_button_->setArrowType(hide ? Qt::LeftArrow : Qt::RightArrow);
607 }
608 
610 {
611  // if a dock widget becomes visible and is resting inside the
612  // left or right dock area, we want to unhide the whole area
613  if (visible)
614  {
615  QDockWidget* dock_widget = dynamic_cast<QDockWidget*>(sender());
616  if (dock_widget)
617  {
618  Qt::DockWidgetArea area = dockWidgetArea(dock_widget);
619  if (area == Qt::LeftDockWidgetArea)
620  {
621  hide_left_dock_button_->setChecked(false);
622  }
623  if (area == Qt::RightDockWidgetArea)
624  {
625  hide_right_dock_button_->setChecked(false);
626  }
627  }
628  }
629 }
630 
632 {
633  Preferences temp_preferences(*preferences_);
634  PreferencesDialog dialog(panel_factory_, &temp_preferences, this);
635  manager_->stopUpdate();
636  if (dialog.exec() == QDialog::Accepted)
637  {
638  // Apply preferences.
639  preferences_ = boost::make_shared<Preferences>(temp_preferences);
640  }
642 }
643 
645 {
646  QString class_id;
647  QString display_name;
648  QStringList empty;
649 
650  NewObjectDialog* dialog =
651  new NewObjectDialog(panel_factory_, "Panel", empty, empty, &class_id, &display_name, this);
652  manager_->stopUpdate();
653  if (dialog->exec() == QDialog::Accepted)
654  {
655  QDockWidget* dock = addPanelByName(display_name, class_id);
656  if (dock)
657  {
658  connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(onDockPanelChange()));
659  }
660  }
662 }
663 
665 {
666  QString class_id;
667  QStringList empty;
668  ToolManager* tool_man = manager_->getToolManager();
669 
670  NewObjectDialog* dialog =
671  new NewObjectDialog(tool_man->getFactory(), "Tool", empty, tool_man->getToolClasses(), &class_id);
672  manager_->stopUpdate();
673  if (dialog->exec() == QDialog::Accepted)
674  {
675  tool_man->addTool(class_id);
676  }
678  activateWindow(); // Force keyboard focus back on main window.
679 }
680 
682 {
683  recent_configs_menu_->clear();
684 
685  D_string::iterator it = recent_configs_.begin();
686  D_string::iterator end = recent_configs_.end();
687  for (; it != end; ++it)
688  {
689  if (!it->empty())
690  {
691  std::string display_name = *it;
692  if (display_name == default_display_config_file_)
693  {
694  display_name += " (default)";
695  }
696  if (display_name.find(home_dir_) == 0)
697  {
698  display_name = ("~" / fs::path(display_name.substr(home_dir_.size()))).BOOST_FILE_STRING();
699  }
700  QString qdisplay_name = QString::fromStdString(display_name);
701  QAction* action = new QAction(qdisplay_name, this);
702  action->setData(QString::fromStdString(*it));
703  connect(action, SIGNAL(triggered()), this, SLOT(onRecentConfigSelected()));
704  recent_configs_menu_->addAction(action);
705  }
706  }
707 }
708 
709 void VisualizationFrame::markRecentConfig(const std::string& path)
710 {
711  D_string::iterator it = std::find(recent_configs_.begin(), recent_configs_.end(), path);
712  if (it != recent_configs_.end())
713  {
714  recent_configs_.erase(it);
715  }
716 
717  recent_configs_.push_front(path);
718 
720  {
721  recent_configs_.pop_back();
722  }
723 
725 }
726 
727 void VisualizationFrame::loadDisplayConfig(const QString& qpath)
728 {
729  std::string path = qpath.toStdString();
730  fs::path actual_load_path = path;
731  bool valid_load_path = fs::is_regular_file(actual_load_path);
732 
733  if (!valid_load_path && fs::portable_posix_name(path))
734  {
735  if (actual_load_path.extension() != "." CONFIG_EXTENSION)
736  actual_load_path += "." CONFIG_EXTENSION;
737  actual_load_path = fs::path(config_dir_) / actual_load_path;
738  if ((valid_load_path = fs::is_regular_file(actual_load_path)))
739  path = actual_load_path.string();
740  }
741 
742  if (!valid_load_path)
743  {
744  actual_load_path = (fs::path(package_path_) / "default.rviz");
745  if (!(valid_load_path = fs::is_regular_file(actual_load_path)))
746  {
747  ROS_ERROR("Default display config '%s' not found. RViz will be very empty at first.",
748  actual_load_path.c_str());
749  return;
750  }
751  }
752  loadDisplayConfigHelper(actual_load_path.BOOST_FILE_STRING());
753 }
754 
755 bool VisualizationFrame::loadDisplayConfigHelper(const std::string& full_path)
756 {
757  // Check if we have unsaved changes to the current config the same
758  // as we do during exit, with the same option to cancel.
759  if (!prepareToExit())
760  {
761  return false;
762  }
763 
764  setWindowModified(false);
765  loading_ = true;
766 
767  std::unique_ptr<LoadingDialog> dialog;
768  if (initialized_)
769  {
770  dialog.reset(new LoadingDialog(this));
771  dialog->show();
772  connect(this, SIGNAL(statusUpdate(const QString&)), dialog.get(), SLOT(showMessage(const QString&)));
773  app_->processEvents(); // make the window correctly appear although running a long-term function
774  }
775 
776  YamlConfigReader reader;
777  Config config;
778  reader.readFile(config, QString::fromStdString(full_path));
779  if (reader.error())
780  return false;
781 
782  load(config);
783 
784  markRecentConfig(full_path);
785 
786  setDisplayConfigFile(full_path);
787 
788  last_config_dir_ = fs::path(full_path).parent_path().BOOST_FILE_STRING();
789 
790  post_load_timer_->start(1000);
791 
792  return true;
793 }
794 
796 {
797  loading_ = false;
798 }
799 
800 void VisualizationFrame::setImageSaveDirectory(const QString& directory)
801 {
802  last_image_dir_ = directory.toStdString();
803 }
804 
806 {
807  if (!loading_)
808  {
809  if (!isWindowModified())
810  {
811  setWindowModified(true);
812  }
813  }
814 }
815 
816 void VisualizationFrame::setDisplayConfigFile(const std::string& path)
817 {
818  display_config_file_ = path;
819 
820  std::string title;
821  if (path == default_display_config_file_)
822  {
823  title = "RViz[*]";
824  }
825  else
826  {
827  title = fs::path(path).BOOST_FILENAME_STRING() + "[*] - RViz";
828  }
829  setWindowTitle(QString::fromStdString(title));
830  Q_EMIT displayConfigFileChanged(QString::fromStdString(path));
831 }
832 
833 bool VisualizationFrame::saveDisplayConfig(const QString& path)
834 {
835  Config config;
836  save(config);
837 
838  YamlConfigWriter writer;
839  writer.writeFile(config, path);
840 
841  if (writer.error())
842  {
843  ROS_ERROR("%s", qPrintable(writer.errorMessage()));
844  error_message_ = writer.errorMessage();
845  return false;
846  }
847  else
848  {
849  setWindowModified(false);
850  error_message_ = "";
851  return true;
852  }
853 }
854 
856 {
857  manager_->save(config.mapMakeChild("Visualization Manager"));
858  savePanels(config.mapMakeChild("Panels"));
859  saveWindowGeometry(config.mapMakeChild("Window Geometry"));
860  savePreferences(config.mapMakeChild("Preferences"));
861  saveToolbars(config.mapMakeChild("Toolbars"));
862 }
863 
864 void VisualizationFrame::load(const Config& config)
865 {
866  manager_->load(config.mapGetChild("Visualization Manager"));
867  loadPanels(config.mapGetChild("Panels"));
868  loadWindowGeometry(config.mapGetChild("Window Geometry"));
869  loadPreferences(config.mapGetChild("Preferences"));
870  configureToolbars(config.mapGetChild("Toolbars"));
871 }
872 
874 {
875  int x, y;
876  if (config.mapGetInt("X", &x) && config.mapGetInt("Y", &y))
877  {
878  move(x, y);
879  }
880 
881  int width, height;
882  if (config.mapGetInt("Width", &width) && config.mapGetInt("Height", &height))
883  {
884  resize(width, height);
885  }
886 
887  QString main_window_config;
888  if (config.mapGetString("QMainWindow State", &main_window_config))
889  {
890  restoreState(QByteArray::fromHex(qPrintable(main_window_config)));
891  }
892 
893  // load panel dock widget states (collapsed or not)
894  QList<PanelDockWidget*> dock_widgets = findChildren<PanelDockWidget*>();
895 
896  for (QList<PanelDockWidget*>::iterator it = dock_widgets.begin(); it != dock_widgets.end(); it++)
897  {
898  Config itConfig = config.mapGetChild((*it)->windowTitle());
899 
900  if (itConfig.isValid())
901  {
902  (*it)->load(itConfig);
903  }
904  }
905 
906  bool b = false;
907  config.mapGetBool("Hide Left Dock", &b);
908  hide_left_dock_button_->setChecked(b);
909  hideLeftDock(b);
910  config.mapGetBool("Hide Right Dock", &b);
911  hideRightDock(b);
912  hide_right_dock_button_->setChecked(b);
913 }
914 
916 {
917  int tool_button_style;
918  if (config.mapGetInt("toolButtonStyle", &tool_button_style))
919  {
920  toolbar_->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(tool_button_style));
921  }
922 }
923 
925 {
926  config.mapSetValue("toolButtonStyle", static_cast<int>(toolbar_->toolButtonStyle()));
927 }
928 
930 {
931  config.mapSetValue("X", x());
932  config.mapSetValue("Y", y());
933  config.mapSetValue("Width", width());
934  config.mapSetValue("Height", height());
935 
936  QByteArray window_state = saveState().toHex();
937  config.mapSetValue("QMainWindow State", window_state.constData());
938 
939  config.mapSetValue("Hide Left Dock", hide_left_dock_button_->isChecked());
940  config.mapSetValue("Hide Right Dock", hide_right_dock_button_->isChecked());
941 
942  // save panel dock widget states (collapsed or not)
943  QList<PanelDockWidget*> dock_widgets = findChildren<PanelDockWidget*>();
944 
945  for (QList<PanelDockWidget*>::iterator it = dock_widgets.begin(); it != dock_widgets.end(); it++)
946  {
947  (*it)->save(config.mapMakeChild((*it)->windowTitle()));
948  }
949 }
950 
952 {
953  // First destroy any existing custom panels.
954  for (int i = custom_panels_.size() - 1; i >= 0; --i)
955  delete custom_panels_[i].dock;
956  custom_panels_.clear();
957 
958  // Then load the ones in the config.
959  int num_custom_panels = config.listLength();
960  for (int i = 0; i < num_custom_panels; i++)
961  {
962  Config panel_config = config.listChildAt(i);
963 
964  QString class_id, name;
965  if (panel_config.mapGetString("Class", &class_id) && panel_config.mapGetString("Name", &name))
966  {
967  QDockWidget* dock = addPanelByName(name, class_id);
968  // This is kind of ridiculous - should just be something like
969  // createPanel() and addPanel() so I can do load() without this
970  // qobject_cast.
971  if (dock)
972  {
973  connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(onDockPanelChange()));
974  Panel* panel = qobject_cast<Panel*>(dock->widget());
975  if (panel)
976  {
977  panel->load(panel_config);
978  }
979  }
980  }
981  }
982 
984 }
985 
987 {
988  config.setType(Config::List); // Not really necessary, but gives an empty list if there are no entries,
989  // instead of an Empty config node.
990 
991  for (int i = 0; i < custom_panels_.size(); i++)
992  {
993  custom_panels_[i].panel->save(config.listAppendNew());
994  }
995 }
996 
998 {
999  config.mapGetBool("PromptSaveOnExit", &(preferences_->prompt_save_on_exit));
1000 }
1001 
1003 {
1004  config.mapSetValue("PromptSaveOnExit", preferences_->prompt_save_on_exit);
1005 }
1006 
1008 {
1009  if (!initialized_)
1010  {
1011  return true;
1012  }
1013 
1015 
1016  if (isWindowModified() && preferences_->prompt_save_on_exit)
1017  {
1018  QMessageBox box(this);
1019  box.setText("There are unsaved changes.");
1020  box.setInformativeText(QString::fromStdString("Save changes to " + display_config_file_ + "?"));
1021  box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1022  box.setDefaultButton(QMessageBox::Save);
1023  manager_->stopUpdate();
1024  int result = box.exec();
1025  manager_->startUpdate();
1026  switch (result)
1027  {
1028  case QMessageBox::Save:
1029  if (saveDisplayConfig(QString::fromStdString(display_config_file_)))
1030  {
1031  return true;
1032  }
1033  else
1034  {
1035  QMessageBox box(this);
1036  box.setWindowTitle("Failed to save.");
1037  box.setText(getErrorMessage());
1038  box.setInformativeText(
1039  QString::fromStdString("Save copy of " + display_config_file_ + " to another file?"));
1040  box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1041  box.setDefaultButton(QMessageBox::Save);
1042  int result = box.exec();
1043  switch (result)
1044  {
1045  case QMessageBox::Save:
1046  onSaveAs();
1047  return true;
1048  case QMessageBox::Discard:
1049  return true;
1050  default:
1051  return false;
1052  }
1053  }
1054  case QMessageBox::Discard:
1055  return true;
1056  default:
1057  return false;
1058  }
1059  }
1060  else
1061  {
1062  return true;
1063  }
1064 }
1065 
1067 {
1068  manager_->stopUpdate();
1069  QString filename = QFileDialog::getOpenFileName(this, "Choose a file to open",
1070  QString::fromStdString(last_config_dir_),
1071  "RViz config files (" CONFIG_EXTENSION_WILDCARD ")");
1072  manager_->startUpdate();
1073 
1074  if (!filename.isEmpty())
1075  {
1076  std::string path = filename.toStdString();
1077 
1078  if (!fs::exists(path))
1079  {
1080  QString message = filename + " does not exist!";
1081  QMessageBox::critical(this, "Config file does not exist", message);
1082  return;
1083  }
1084 
1085  loadDisplayConfig(filename);
1086  }
1087 }
1088 
1090 {
1091  if (!initialized_)
1092  {
1093  return;
1094  }
1095 
1097 
1098  if (!saveDisplayConfig(QString::fromStdString(display_config_file_)))
1099  {
1100  manager_->stopUpdate();
1101  QMessageBox box(this);
1102  box.setWindowTitle("Failed to save.");
1103  box.setText(getErrorMessage());
1104  box.setInformativeText(
1105  QString::fromStdString("Save copy of " + display_config_file_ + " to another file?"));
1106  box.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
1107  box.setDefaultButton(QMessageBox::Save);
1108  if (box.exec() == QMessageBox::Save)
1109  {
1110  onSaveAs();
1111  }
1112  manager_->startUpdate();
1113  }
1114 }
1115 
1117 {
1118  manager_->stopUpdate();
1119  QString q_filename = QFileDialog::getSaveFileName(this, "Choose a file to save to",
1120  QString::fromStdString(last_config_dir_),
1121  "RViz config files (" CONFIG_EXTENSION_WILDCARD ")");
1122  manager_->startUpdate();
1123 
1124  if (!q_filename.isEmpty())
1125  {
1126  std::string filename = q_filename.toStdString();
1127  fs::path path(filename);
1128  if (path.extension() != "." CONFIG_EXTENSION)
1129  {
1130  filename += "." CONFIG_EXTENSION;
1131  }
1132 
1133  if (!saveDisplayConfig(QString::fromStdString(filename)))
1134  {
1135  QMessageBox::critical(this, "Failed to save.", getErrorMessage());
1136  }
1137 
1138  markRecentConfig(filename);
1139  last_config_dir_ = fs::path(filename).parent_path().BOOST_FILE_STRING();
1140  setDisplayConfigFile(filename);
1141  }
1142 }
1143 
1145 {
1146  ScreenshotDialog* dialog =
1147  new ScreenshotDialog(this, render_panel_, QString::fromStdString(last_image_dir_));
1148  connect(dialog, SIGNAL(savedInDirectory(const QString&)), this,
1149  SLOT(setImageSaveDirectory(const QString&)));
1150  dialog->show();
1151 }
1152 
1154 {
1155  QAction* action = dynamic_cast<QAction*>(sender());
1156  if (action)
1157  {
1158  std::string path = action->data().toString().toStdString();
1159  if (!path.empty())
1160  {
1161  if (!fs::exists(path))
1162  {
1163  QString message = QString::fromStdString(path) + " does not exist!";
1164  QMessageBox::critical(this, "Config file does not exist", message);
1165  return;
1166  }
1167 
1168  loadDisplayConfig(QString::fromStdString(path));
1169  }
1170  }
1171 }
1172 
1174 {
1175  QAction* action = new QAction(tool->getName(), toolbar_actions_);
1176  action->setIcon(tool->getIcon());
1177  action->setIconText(tool->getName());
1178  action->setCheckable(true);
1179  toolbar_->insertAction(add_tool_action_, action);
1180  action_to_tool_map_[action] = tool;
1181  tool_to_action_map_[tool] = action;
1182 
1183  remove_tool_menu_->addAction(tool->getName());
1184 
1185  QObject::connect(tool, &Tool::nameChanged, this, &VisualizationFrame::onToolNameChanged);
1186 }
1187 
1188 void VisualizationFrame::onToolNameChanged(const QString& name)
1189 {
1190  // Early return if the tool is not present
1191  auto it = tool_to_action_map_.find(qobject_cast<Tool*>(sender()));
1192  if (it == tool_to_action_map_.end())
1193  return;
1194 
1195  // Change the name of the action
1196  it->second->setIconText(name);
1197 }
1198 
1200 {
1201  Tool* tool = action_to_tool_map_[action];
1202 
1203  if (tool)
1204  {
1206  }
1207 }
1208 
1209 void VisualizationFrame::onToolbarRemoveTool(QAction* remove_tool_menu_action)
1210 {
1211  QString name = remove_tool_menu_action->text();
1212  for (int i = 0; i < manager_->getToolManager()->numTools(); i++)
1213  {
1214  Tool* tool = manager_->getToolManager()->getTool(i);
1215  if (tool->getName() == name)
1216  {
1218  return;
1219  }
1220  }
1221 }
1222 
1223 void VisualizationFrame::onButtonStyleTool(QAction* button_style_tool_menu_action)
1224 {
1225  toolbar_->setToolButtonStyle(
1226  static_cast<Qt::ToolButtonStyle>(button_style_tool_menu_action->data().toInt()));
1227 }
1228 
1230 {
1231  QAction* action = tool_to_action_map_[tool];
1232  if (action)
1233  {
1234  toolbar_actions_->removeAction(action);
1235  toolbar_->removeAction(action);
1236  tool_to_action_map_.erase(tool);
1237  action_to_tool_map_.erase(action);
1238  }
1239  QString tool_name = tool->getName();
1240  QList<QAction*> remove_tool_actions = remove_tool_menu_->actions();
1241  for (int i = 0; i < remove_tool_actions.size(); i++)
1242  {
1243  QAction* removal_action = remove_tool_actions.at(i);
1244  if (removal_action->text() == tool_name)
1245  {
1246  remove_tool_menu_->removeAction(removal_action);
1247  break;
1248  }
1249  }
1250 }
1251 
1253 {
1254  QAction* action = tool_to_action_map_[tool];
1255  action->setIcon(tool->getIcon());
1256  action->setIconText(tool->getName());
1257 }
1258 
1260 {
1261  QAction* action = tool_to_action_map_[tool];
1262  if (action)
1263  {
1264  action->setChecked(true);
1265  }
1266 }
1267 
1269 {
1270  if (!show_help_action_)
1271  {
1272  QDockWidget* dock = addPanelByName("Help", "rviz/Help");
1273  show_help_action_ = dock->toggleViewAction();
1274  connect(dock, SIGNAL(destroyed(QObject*)), this, SLOT(onHelpDestroyed()));
1275  }
1276  else
1277  {
1278  // show_help_action_ is a toggle action, so trigger() changes its
1279  // state. Therefore we must force it to the opposite state from
1280  // what we want before we call trigger(). (I think.)
1281  show_help_action_->setChecked(false);
1282  show_help_action_->trigger();
1283  }
1284 }
1285 
1287 {
1288  show_help_action_ = nullptr;
1289 }
1290 
1292 {
1293  QDesktopServices::openUrl(QUrl("http://wiki.ros.org/rviz"));
1294 }
1295 
1297 {
1298  QString about_text = QString("This is RViz version %1 (%2).\n"
1299  "\n"
1300  "Compiled against Qt version %3."
1301  "\n"
1302  "Compiled against OGRE version %4.%5.%6%7 (%8).")
1303  .arg(get_version().c_str())
1304  .arg(get_distro().c_str())
1305  .arg(QT_VERSION_STR)
1306  .arg(OGRE_VERSION_MAJOR)
1307  .arg(OGRE_VERSION_MINOR)
1308  .arg(OGRE_VERSION_PATCH)
1309  .arg(OGRE_VERSION_SUFFIX)
1310  .arg(OGRE_VERSION_NAME);
1311 
1312  QMessageBox::about(QApplication::activeWindow(), "About", about_text);
1313 }
1314 
1316 {
1317  QList<QTabBar*> tab_bars = findChildren<QTabBar*>(QString(), Qt::FindDirectChildrenOnly);
1318  for (QList<QTabBar*>::iterator it = tab_bars.begin(); it != tab_bars.end(); it++)
1319  {
1320  (*it)->setElideMode(Qt::ElideNone);
1321  }
1322 }
1323 
1325 {
1326  return this;
1327 }
1328 
1330 {
1331  for (int i = 0; i < custom_panels_.size(); ++i)
1332  {
1333  if (custom_panels_[i].dock == dock)
1334  {
1335  auto& record = custom_panels_[i];
1336  record.delete_action->deleteLater();
1337  delete_view_menu_->removeAction(record.delete_action);
1338  delete_view_menu_->setDisabled(delete_view_menu_->actions().isEmpty());
1339  custom_panels_.removeAt(i);
1341  return;
1342  }
1343  }
1344 }
1345 
1347 {
1348  // This should only be called as a SLOT from a QAction in the
1349  // "delete panel" submenu, so the sender will be one of the QActions
1350  // stored as "delete_action" in a PanelRecord. This code looks for
1351  // a delete_action in custom_panels_ matching sender() and removes
1352  // the panel associated with it.
1353  if (QAction* action = qobject_cast<QAction*>(sender()))
1354  {
1355  for (int i = 0; i < custom_panels_.size(); i++)
1356  {
1357  if (custom_panels_[i].delete_action == action)
1358  {
1359  delete custom_panels_[i].dock;
1360  return;
1361  }
1362  }
1363  }
1364 }
1365 
1367 {
1368  Qt::WindowStates state = windowState();
1369  if (full_screen == state.testFlag(Qt::WindowFullScreen))
1370  return;
1371  Q_EMIT(fullScreenChange(full_screen));
1372 
1373  // when switching to fullscreen, remember visibility state of toolbar
1374  if (full_screen)
1375  toolbar_visible_ = toolbar_->isVisible();
1376  menuBar()->setVisible(!full_screen);
1377  toolbar_->setVisible(!full_screen && toolbar_visible_);
1378  statusBar()->setVisible(!full_screen);
1379  setHideButtonVisibility(!full_screen);
1380 
1381  if (full_screen)
1382  setWindowState(state | Qt::WindowFullScreen);
1383  else
1384  setWindowState(state & ~Qt::WindowFullScreen);
1385  show();
1386 }
1387 
1389 {
1390  setFullScreen(false);
1391 }
1392 
1393 QDockWidget* VisualizationFrame::addPanelByName(const QString& name,
1394  const QString& class_id,
1395  Qt::DockWidgetArea area,
1396  bool floating)
1397 {
1398  QString error;
1399  Panel* panel = panel_factory_->make(class_id, &error);
1400  if (!panel)
1401  {
1402  panel = new FailedPanel(class_id, error);
1403  }
1404  panel->setName(name);
1405  connect(panel, SIGNAL(configChanged()), this, SLOT(setDisplayConfigModified()));
1406 
1407  PanelRecord record;
1408  record.dock = addPane(name, panel, area, floating);
1409  record.panel = panel;
1410  record.name = name;
1411  record.delete_action = delete_view_menu_->addAction(name, this, SLOT(onDeletePanel()));
1412  connect(record.dock, &QObject::destroyed, this, &VisualizationFrame::onPanelDeleted);
1413  custom_panels_.append(record);
1414  delete_view_menu_->setEnabled(true);
1415 
1416  record.panel->initialize(manager_);
1417 
1418  record.dock->setIcon(panel_factory_->getIcon(class_id));
1419 
1420  return record.dock;
1421 }
1422 
1424 VisualizationFrame::addPane(const QString& name, QWidget* panel, Qt::DockWidgetArea area, bool floating)
1425 {
1426  PanelDockWidget* dock;
1427  dock = new PanelDockWidget(name);
1428  addDockWidget(area, dock);
1429 
1430  dock->setContentWidget(panel);
1431  dock->setFloating(floating);
1432  dock->setObjectName(name); // QMainWindow::saveState() needs objectName to be set.
1433 
1434  // we want to know when that panel becomes visible
1435  connect(dock, SIGNAL(visibilityChanged(bool)), this, SLOT(onDockPanelVisibilityChange(bool)));
1436  connect(this, SIGNAL(fullScreenChange(bool)), dock, SLOT(overrideVisibility(bool)));
1437 
1438  QAction* toggle_action = dock->toggleViewAction();
1439  view_menu_->addAction(toggle_action);
1440 
1441  connect(toggle_action, SIGNAL(triggered(bool)), this, SLOT(setDisplayConfigModified()));
1442  connect(dock, SIGNAL(closed()), this, SLOT(setDisplayConfigModified()));
1443 
1444  dock->installEventFilter(geom_change_detector_);
1445 
1446  // repair/update visibility status
1447  hideLeftDock(area == Qt::LeftDockWidgetArea ? false : hide_left_dock_button_->isChecked());
1448  hideRightDock(area == Qt::RightDockWidgetArea ? false : hide_right_dock_button_->isChecked());
1449 
1450  return dock;
1451 }
1452 
1453 } // 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
void onPanelDeleted(QObject *dock)
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 Sat May 27 2023 02:06:25