node_click_handler.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2016, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE 
00021 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00023 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00024 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00027 // DAMAGE.
00028 //
00029 // *****************************************************************************
00030 
00031 #include <swri_console/node_click_handler.h>
00032 #include <swri_console/node_list_model.h>
00033 
00034 #include <ros/ros.h>
00035 #include <roscpp/GetLoggers.h>
00036 #include <roscpp/SetLoggerLevel.h>
00037 
00038 #include <QMessageBox>
00039 #include <QTextStream>
00040 
00041 namespace swri_console
00042 {
00043   const std::string NodeClickHandler::ALL_LOGGERS = "All Loggers";
00044   const std::string NodeClickHandler::GET_LOGGERS_SVC = "/get_loggers";
00045   const std::string NodeClickHandler::SET_LOGGER_LEVEL_SVC = "/set_logger_level";
00046 
00047   bool NodeClickHandler::eventFilter(QObject* obj, QEvent* event)
00048   {
00049     QContextMenuEvent* context_event;
00050     QListView* list;
00051 
00052     switch (event->type()) {
00053       case QEvent::ContextMenu:
00054         context_event = static_cast<QContextMenuEvent*>(event);
00055         // First, make sure we clicked on the list and have an item in the list
00056         // under the mouse cursor.
00057         list = static_cast<QListView*>(obj);
00058         if (list == NULL) {
00059           return false;
00060         }
00061 
00062         return showContextMenu(list, context_event);
00063       default:
00064         // Pass through all other events
00065         return QObject::eventFilter(obj, event);
00066     }
00067   }
00068 
00069   bool NodeClickHandler::showContextMenu(QListView* list, QContextMenuEvent* event)
00070   {
00071     QModelIndexList index_list = list->selectionModel()->selectedIndexes();
00072     if (index_list.isEmpty()) {
00073       return false;
00074     }
00075 
00076     // Now get the node name that was clicked on and make a service call to
00077     // get all of the loggers registered for that node.
00078     NodeListModel* model = static_cast<NodeListModel*>(list->model());
00079     node_name_ = model->nodeName(index_list.first());
00080 
00081     std::string service_name = node_name_ + GET_LOGGERS_SVC;
00082     ros::ServiceClient client = nh_.serviceClient<roscpp::GetLoggers>(service_name);
00089     if (!client.waitForExistence(ros::Duration(2.0))) {
00090       ROS_WARN("Timed out while waiting for service at %s.", service_name.c_str());
00091       QMessageBox::warning(list, "Error Getting Loggers", "Timed out waiting for get_loggers service.");
00092       return false;
00093     }
00094 
00095     roscpp::GetLoggers srv;
00096 
00097     QMenu menu(list);
00098     QAction* label = menu.addAction(QString::fromStdString(node_name_ + " loggers:"));
00099     label->setDisabled(true);
00100 
00101     ROS_DEBUG("Getting loggers for %s...", node_name_.c_str());
00102     if (callService(client, srv)) {
00103       all_loggers_.clear();
00104       menu.addMenu(createMenu(QString::fromStdString(ALL_LOGGERS), ""));
00105       Q_FOREACH(const roscpp::Logger& logger, srv.response.loggers) {
00106         ROS_DEBUG("Log level for %s is %s", logger.name.c_str(), logger.level.c_str());
00107         all_loggers_.push_back(logger.name);
00108         QString logger_name = QString::fromStdString(logger.name);
00109 
00110         menu.addMenu(createMenu(logger_name, QString::fromStdString(logger.level)));
00111       }
00112     }
00113     else {
00114       std::string error = "Service call to get_loggers failed.";
00115       ROS_WARN("%s", error.c_str());
00116       QMessageBox::warning(list, "Service Call Failed", error.c_str());
00117     }
00118 
00119     menu.exec(event->globalPos());
00120 
00121     return false;
00122   }
00123 
00124   QMenu* NodeClickHandler::createMenu(const QString& logger_name, const QString& current_level)
00125   {
00126     QString action_label;
00127     QTextStream stream(&action_label);
00128     stream << logger_name;
00129     if (!current_level.isEmpty()) {
00130       stream << " (" << current_level.toUpper() << ")";
00131     }
00132 
00133     QMenu* nodeMenu = new QMenu(action_label);
00134 
00135     const QString levels[] = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
00136 
00137     for (int i = 0; i < 5; i++) {
00138       QAction* action = nodeMenu->addAction(levels[i], this, SLOT(logLevelClicked()));
00139       action->setData(logger_name);
00140     }
00141 
00142     return nodeMenu;
00143   }
00144 
00145   void NodeClickHandler::logLevelClicked()
00146   {
00147     QAction* action = static_cast<QAction*>(sender());
00148 
00149     std::string logger = action->data().toString().toStdString();
00150     std::string level = action->text().toStdString();
00151     ROS_DEBUG("Setting log level for %s/%s to %s", node_name_.c_str(), logger.c_str(), level.c_str());
00152 
00153     std::string service_name = node_name_ + SET_LOGGER_LEVEL_SVC;
00154 
00155     ros::ServiceClient client = nh_.serviceClient<roscpp::SetLoggerLevel>(service_name);
00156     if (!client.waitForExistence(ros::Duration(2.0))) {
00157       ROS_WARN("Timed out while waiting for service at %s.", service_name.c_str());
00158       QMessageBox::warning(NULL, "Error Getting Loggers", "Timed out waiting for set_logger_level service.");
00159       return;
00160     }
00161 
00162     std::vector<std::string> target_loggers;
00163     if (logger == ALL_LOGGERS) {
00164       target_loggers = all_loggers_;
00165     }
00166     else {
00167       target_loggers.push_back(logger);
00168     }
00169 
00170     Q_FOREACH (const std::string& logger_name, target_loggers) {
00171       roscpp::SetLoggerLevel srv;
00172       srv.request.level = level;
00173       srv.request.logger = logger_name;
00174       if (callService(client, srv)) {
00175         ROS_DEBUG("Set logger level.");
00176       }
00177       else {
00178         ROS_WARN("Service call to %s failed.", service_name.c_str());
00179         QMessageBox::warning(NULL, "Error Setting Log Level", "Failed to set logger level.");
00180       }
00181     }
00182   }
00183 }
00184 


swri_console
Author(s):
autogenerated on Sat Jun 8 2019 18:46:13