Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
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         
00056         
00057         list = static_cast<QListView*>(obj);
00058         if (list == NULL) {
00059           return false;
00060         }
00061 
00062         return showContextMenu(list, context_event);
00063       default:
00064         
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     
00077     
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