node_click_handler.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2016, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
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 Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from 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 Southwest Research Institute® BE LIABLE
21 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27 // DAMAGE.
28 //
29 // *****************************************************************************
30 
33 
34 #include <ros/ros.h>
35 #include <roscpp/GetLoggers.h>
36 #include <roscpp/SetLoggerLevel.h>
37 
38 #include <QMessageBox>
39 #include <QTextStream>
40 
41 namespace swri_console
42 {
43  const std::string NodeClickHandler::ALL_LOGGERS = "All Loggers";
44  const std::string NodeClickHandler::GET_LOGGERS_SVC = "/get_loggers";
45  const std::string NodeClickHandler::SET_LOGGER_LEVEL_SVC = "/set_logger_level";
46 
47  bool NodeClickHandler::eventFilter(QObject* obj, QEvent* event)
48  {
49  QContextMenuEvent* context_event;
50  QListView* list;
51 
52  switch (event->type()) {
53  case QEvent::ContextMenu:
54  context_event = static_cast<QContextMenuEvent*>(event);
55  // First, make sure we clicked on the list and have an item in the list
56  // under the mouse cursor.
57  list = static_cast<QListView*>(obj);
58  if (list == NULL) {
59  return false;
60  }
61 
62  return showContextMenu(list, context_event);
63  default:
64  // Pass through all other events
65  return QObject::eventFilter(obj, event);
66  }
67  }
68 
69  bool NodeClickHandler::showContextMenu(QListView* list, QContextMenuEvent* event)
70  {
71  QModelIndexList index_list = list->selectionModel()->selectedIndexes();
72  if (index_list.isEmpty()) {
73  return false;
74  }
75 
76  // Now get the node name that was clicked on and make a service call to
77  // get all of the loggers registered for that node.
78  NodeListModel* model = static_cast<NodeListModel*>(list->model());
79  node_name_ = model->nodeName(index_list.first());
80 
81  std::string service_name = node_name_ + GET_LOGGERS_SVC;
82  ros::ServiceClient client = nh_.serviceClient<roscpp::GetLoggers>(service_name);
89  if (!client.waitForExistence(ros::Duration(2.0))) {
90  ROS_WARN("Timed out while waiting for service at %s.", service_name.c_str());
91  QMessageBox::warning(list, "Error Getting Loggers", "Timed out waiting for get_loggers service.");
92  return false;
93  }
94 
95  roscpp::GetLoggers srv;
96 
97  QMenu menu(list);
98  QAction* label = menu.addAction(QString::fromStdString(node_name_ + " loggers:"));
99  label->setDisabled(true);
100 
101  ROS_DEBUG("Getting loggers for %s...", node_name_.c_str());
102  if (callService(client, srv)) {
103  all_loggers_.clear();
104  menu.addMenu(createMenu(QString::fromStdString(ALL_LOGGERS), ""));
105  Q_FOREACH(const roscpp::Logger& logger, srv.response.loggers) {
106  ROS_DEBUG("Log level for %s is %s", logger.name.c_str(), logger.level.c_str());
107  all_loggers_.push_back(logger.name);
108  QString logger_name = QString::fromStdString(logger.name);
109 
110  menu.addMenu(createMenu(logger_name, QString::fromStdString(logger.level)));
111  }
112  }
113  else {
114  std::string error = "Service call to get_loggers failed.";
115  ROS_WARN("%s", error.c_str());
116  QMessageBox::warning(list, "Service Call Failed", error.c_str());
117  }
118 
119  menu.exec(event->globalPos());
120 
121  return false;
122  }
123 
124  QMenu* NodeClickHandler::createMenu(const QString& logger_name, const QString& current_level)
125  {
126  QString action_label;
127  QTextStream stream(&action_label);
128  stream << logger_name;
129  if (!current_level.isEmpty()) {
130  stream << " (" << current_level.toUpper() << ")";
131  }
132 
133  QMenu* nodeMenu = new QMenu(action_label);
134 
135  const QString levels[] = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
136 
137  for (int i = 0; i < 5; i++) {
138  QAction* action = nodeMenu->addAction(levels[i], this, SLOT(logLevelClicked()));
139  action->setData(logger_name);
140  }
141 
142  return nodeMenu;
143  }
144 
146  {
147  QAction* action = static_cast<QAction*>(sender());
148 
149  std::string logger = action->data().toString().toStdString();
150  std::string level = action->text().toStdString();
151  ROS_DEBUG("Setting log level for %s/%s to %s", node_name_.c_str(), logger.c_str(), level.c_str());
152 
153  std::string service_name = node_name_ + SET_LOGGER_LEVEL_SVC;
154 
155  ros::ServiceClient client = nh_.serviceClient<roscpp::SetLoggerLevel>(service_name);
156  if (!client.waitForExistence(ros::Duration(2.0))) {
157  ROS_WARN("Timed out while waiting for service at %s.", service_name.c_str());
158  QMessageBox::warning(NULL, "Error Getting Loggers", "Timed out waiting for set_logger_level service.");
159  return;
160  }
161 
162  std::vector<std::string> target_loggers;
163  if (logger == ALL_LOGGERS) {
164  target_loggers = all_loggers_;
165  }
166  else {
167  target_loggers.push_back(logger);
168  }
169 
170  Q_FOREACH (const std::string& logger_name, target_loggers) {
171  roscpp::SetLoggerLevel srv;
172  srv.request.level = level;
173  srv.request.logger = logger_name;
174  if (callService(client, srv)) {
175  ROS_DEBUG("Set logger level.");
176  }
177  else {
178  ROS_WARN("Service call to %s failed.", service_name.c_str());
179  QMessageBox::warning(NULL, "Error Setting Log Level", "Failed to set logger level.");
180  }
181  }
182  }
183 }
184 
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
bool callService(ros::ServiceClient &client, T &service, int timeout_secs=5)
bool showContextMenu(QListView *list, QContextMenuEvent *event)
#define ROS_WARN(...)
std::string nodeName(const QModelIndex &index) const
bool waitForExistence(ros::Duration timeout=ros::Duration(-1))
QMenu * createMenu(const QString &logger_name, const QString &current_level)
bool eventFilter(QObject *obj, QEvent *event)
static const std::string SET_LOGGER_LEVEL_SVC
static const std::string ALL_LOGGERS
std::vector< std::string > all_loggers_
#define ROS_DEBUG(...)
static const std::string GET_LOGGERS_SVC


swri_console
Author(s):
autogenerated on Fri Apr 3 2020 03:20:03