Package node_manager_fkie :: Module run_dialog
[frames] | no frames]

Source Code for Module node_manager_fkie.run_dialog

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  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 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Fraunhofer nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32   
 33  from python_qt_binding import QtGui 
 34  from python_qt_binding import QtCore 
 35   
 36  import os 
 37   
 38  import node_manager_fkie as nm 
 39  from packages_thread import PackagesThread 
 40   
 41   
42 -class RunDialog(QtGui.QDialog):
43 ''' 44 A dialog to run a ROS node without configuration 45 ''' 46
47 - def __init__(self, host, masteruri=None, parent=None):
48 QtGui.QDialog.__init__(self, parent) 49 self.host = host 50 self.setWindowTitle('Run') 51 self.verticalLayout = QtGui.QVBoxLayout(self) 52 self.verticalLayout.setObjectName("verticalLayout") 53 54 self.content = QtGui.QWidget() 55 self.contentLayout = QtGui.QFormLayout(self.content) 56 self.contentLayout.setVerticalSpacing(0) 57 self.verticalLayout.addWidget(self.content) 58 59 self.packages = None 60 61 package_label = QtGui.QLabel("Package:", self.content) 62 self.package_field = QtGui.QComboBox(self.content) 63 self.package_field.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically) 64 self.package_field.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) 65 self.package_field.setEditable(True) 66 self.contentLayout.addRow(package_label, self.package_field) 67 binary_label = QtGui.QLabel("Binary:", self.content) 68 self.binary_field = QtGui.QComboBox(self.content) 69 # self.binary_field.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) 70 self.binary_field.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) 71 self.binary_field.setEditable(True) 72 self.contentLayout.addRow(binary_label, self.binary_field) 73 ns_name_label = QtGui.QLabel("NS/Name:", self.content) 74 self.ns_field = QtGui.QComboBox(self.content) 75 self.ns_field.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) 76 self.ns_field.setEditable(True) 77 ns_history = nm.history().cachedParamValues('run_dialog/NS') 78 ns_history.insert(0, '/') 79 self.ns_field.addItems(ns_history) 80 self.name_field = QtGui.QLineEdit(self.content) 81 self.name_field.setEnabled(False) 82 horizontalLayout = QtGui.QHBoxLayout() 83 horizontalLayout.addWidget(self.ns_field) 84 horizontalLayout.addWidget(self.name_field) 85 self.contentLayout.addRow(ns_name_label, horizontalLayout) 86 args_label = QtGui.QLabel("Args:", self.content) 87 self.args_field = QtGui.QComboBox(self.content) 88 self.args_field.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength) 89 self.args_field.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) 90 self.args_field.setEditable(True) 91 self.contentLayout.addRow(args_label, self.args_field) 92 args_history = nm.history().cachedParamValues('run_dialog/Args') 93 args_history.insert(0, '') 94 self.args_field.addItems(args_history) 95 96 host_label = QtGui.QLabel("Host:", self.content) 97 self.host_field = QtGui.QComboBox(self.content) 98 # self.host_field.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) 99 self.host_field.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) 100 self.host_field.setEditable(True) 101 host_label.setBuddy(self.host_field) 102 self.contentLayout.addRow(host_label, self.host_field) 103 self.host_history = host_history = nm.history().cachedParamValues('/Host') 104 if self.host in host_history: 105 host_history.remove(self.host) 106 host_history.insert(0, self.host) 107 self.host_field.addItems(host_history) 108 109 master_label = QtGui.QLabel("ROS Master URI:", self.content) 110 self.master_field = QtGui.QComboBox(self.content) 111 self.master_field.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) 112 self.master_field.setEditable(True) 113 master_label.setBuddy(self.host_field) 114 self.contentLayout.addRow(master_label, self.master_field) 115 self.master_history = master_history = nm.history().cachedParamValues('/Optional Parameter/ROS Master URI') 116 self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri 117 if self.masteruri in master_history: 118 master_history.remove(self.masteruri) 119 master_history.insert(0, self.masteruri) 120 self.master_field.addItems(master_history) 121 122 self.buttonBox = QtGui.QDialogButtonBox(self) 123 self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel) 124 self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 125 self.buttonBox.setObjectName("buttonBox") 126 self.verticalLayout.addWidget(self.buttonBox) 127 128 self.package_field.setFocus(QtCore.Qt.TabFocusReason) 129 self.package = '' 130 self.binary = '' 131 132 if self.packages is None: 133 self.package_field.addItems(['packages searching...']) 134 self.package_field.setCurrentIndex(0) 135 self._fill_packages_thread = PackagesThread() 136 self._fill_packages_thread.packages.connect(self._fill_packages) 137 self._fill_packages_thread.start() 138 139 QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept) 140 QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject) 141 QtCore.QMetaObject.connectSlotsByName(self) 142 self.package_field.activated[str].connect(self.on_package_selected) 143 self.package_field.textChanged.connect(self.on_package_selected) 144 self.binary_field.activated[str].connect(self.on_binary_selected)
145
146 - def _fill_packages(self, packages):
147 # fill the input fields 148 self.packages = packages 149 packages = packages.keys() 150 packages.sort() 151 self.package_field.clear() 152 self.package_field.clearEditText() 153 self.package_field.addItems(packages)
154
155 - def run_params(self):
156 ''' 157 Runs the selected node, or do nothing. 158 :return: a tuple with host, package, binary, name, args, maseruri or empty tuple on errors 159 ''' 160 self.binary = self.binary_field.currentText() 161 self.host = self.host_field.currentText() if self.host_field.currentText() else self.host 162 self.masteruri = self.master_field.currentText() if self.master_field.currentText() else self.masteruri 163 if not self.host in self.host_history and self.host != 'localhost' and self.host != '127.0.0.1': 164 nm.history().add2HostHistory(self.host) 165 ns = self.ns_field.currentText() 166 if ns and ns != '/': 167 nm.history().addParamCache('run_dialog/NS', ns) 168 args = self.args_field.currentText() 169 if args: 170 nm.history().addParamCache('run_dialog/Args', args) 171 if self.package and self.binary: 172 nm.history().addParamCache('/Host', self.host) 173 return (self.host, self.package, self.binary, self.name_field.text(), ('__ns:=%s %s'%(ns, args)).split(' '), None if self.masteruri == 'ROS_MASTER_URI' else self.masteruri) 174 return ()
175
176 - def _getBinaries(self, path):
177 result = {} 178 if os.path.isdir(path): 179 fileList = os.listdir(path) 180 for f in fileList: 181 if f and f[0] != '.' and not f in ['build'] and not f.endswith('.cfg') and not f.endswith('.so'): 182 ret = self._getBinaries(os.path.join(path, f)) 183 result = dict(ret.items() + result.items()) 184 elif os.path.isfile(path) and os.access(path, os.X_OK): 185 # create a selection for binaries 186 return {os.path.basename(path) : path} 187 return result
188
189 - def on_package_selected(self, package):
190 self.binary_field.clear() 191 if self.packages and self.packages.has_key(package): 192 self.binary_field.setEnabled(True) 193 self.args_field.setEnabled(True) 194 self.ns_field.setEnabled(True) 195 self.name_field.setEnabled(True) 196 path = self.packages[package] 197 binaries = self._getBinaries(path).keys() 198 try: 199 # find binaries in catkin workspace 200 from catkin.find_in_workspaces import find_in_workspaces as catkin_find 201 search_paths = catkin_find(search_dirs=['libexec', 'share'], project=package, first_matching_workspace_only=True) 202 for p in search_paths: 203 binaries += self._getBinaries(p).keys() 204 except: 205 pass 206 binaries.sort() 207 self.binary_field.addItems(binaries) 208 self.package = package 209 root, ext = os.path.splitext(os.path.basename(self.binary_field.currentText())) 210 self.name_field.setText(root)
211
212 - def on_binary_selected(self, binary):
213 root, ext = os.path.splitext(os.path.basename(binary)) 214 self.name_field.setText(root)
215