Home | Trees | Indices | Help |
---|
|
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 import os 33 from datetime import datetime 34 35 from python_qt_binding import QtGui 36 from python_qt_binding import QtCore 37 from python_qt_binding import loadUi 38 39 import rospy 40 from rosgraph_msgs.msg import Log 41 42 import node_manager_fkie as nm 43 from .common import masteruri_from_ros, package_name 44 from .detailed_msg_box import WarningMessageBox 45 from .launch_list_model import LaunchListModel, LaunchItem 46 from .progress_queue import ProgressQueue, ProgressThread 47 from .parameter_dialog import ParameterDialog 4850 ''' 51 Launch file browser. 52 ''' 53 54 load_signal = QtCore.Signal(str) 55 ''' load the launch file ''' 56 load_as_default_signal = QtCore.Signal(str, str) 57 ''' load the launch file as default (path, host) ''' 58 edit_signal = QtCore.Signal(list) 59 ''' list of paths to open in an editor ''' 60 transfer_signal = QtCore.Signal(list) 61 ''' list of paths selected for transfer ''' 6234664 ''' 65 Creates the window, connects the signals and init the class. 66 ''' 67 QtGui.QDockWidget.__init__(self, parent) 68 # initialize parameter 69 self.__current_path = os.path.expanduser('~') 70 # load the UI file 71 ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'LaunchFilesDockWidget.ui') 72 loadUi(ui_file, self) 73 # initialize the view for the launch files 74 self.launchlist_model = LaunchListModel() 75 self.launchlist_proxyModel = QtGui.QSortFilterProxyModel(self) 76 self.launchlist_proxyModel.setSourceModel(self.launchlist_model) 77 self.xmlFileView.setModel(self.launchlist_proxyModel) 78 self.xmlFileView.setAlternatingRowColors(True) 79 self.xmlFileView.activated.connect(self.on_launch_selection_activated) 80 self.xmlFileView.setDragDropMode(QtGui.QAbstractItemView.DragOnly) 81 self.xmlFileView.setDragEnabled(True) 82 sm = self.xmlFileView.selectionModel() 83 sm.selectionChanged.connect(self.on_xmlFileView_selection_changed) 84 # self.searchPackageLine.setVisible(False) 85 self.searchPackageLine.textChanged.connect(self.set_package_filter) 86 self.searchPackageLine.focusInEvent = self._searchline_focusInEvent 87 # connect to the button signals 88 self.refreshXmlButton.clicked.connect(self.on_refresh_xml_clicked) 89 self.editXmlButton.clicked.connect(self.on_edit_xml_clicked) 90 self.newXmlButton.clicked.connect(self.on_new_xml_clicked) 91 self.openXmlButton.clicked.connect(self.on_open_xml_clicked) 92 self.transferButton.clicked.connect(self.on_transfer_file_clicked) 93 self.loadXmlButton.clicked.connect(self.on_load_xml_clicked) 94 self.loadXmlAsDefaultButton.clicked.connect(self.on_load_as_default) 95 # creates a default config menu 96 start_menu = QtGui.QMenu(self) 97 self.loadDeafaultAtHostAct = QtGui.QAction("&Load default config on host", self, statusTip="Loads the default config at given host", triggered=self.on_load_as_default_at_host) 98 start_menu.addAction(self.loadDeafaultAtHostAct) 99 self.loadXmlAsDefaultButton.setMenu(start_menu) 100 #initialize the progress queue 101 self.progress_queue = ProgressQueue(self.progressFrame_cfg, self.progressBar_cfg, self.progressCancelButton_cfg)102104 ''' 105 Cancel the executing queued actions. This method must be 106 called at the exit! 107 ''' 108 self.progress_queue.stop()109111 ''' 112 Tries to load the launch file, if one was activated. 113 ''' 114 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 115 for item in selected: 116 try: 117 file = self.launchlist_model.expandItem(item.name, item.path, item.id) 118 self.searchPackageLine.setText('') 119 if not file is None: 120 if item.isLaunchFile(): 121 self.launchlist_model.add2LoadHistory(item.path) 122 key_mod = QtGui.QApplication.keyboardModifiers() 123 if (key_mod & QtCore.Qt.ShiftModifier): 124 self.load_as_default_signal.emit(item.path, None) 125 else: 126 self.load_signal.emit(item.path) 127 elif item.isConfigFile(): 128 self.edit_signal.emit([file]) 129 except Exception as e: 130 rospy.logwarn("Error while load launch file %s: %s"%(item, e)) 131 WarningMessageBox(QtGui.QMessageBox.Warning, "Load error", 132 'Error while load launch file:\n%s'%item.name, 133 "%s"%e).exec_()134 # self.launchlist_model.reloadCurrentPath() 135137 ''' 138 On selection of a launch file, the buttons are enabled otherwise disabled. 139 ''' 140 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 141 for item in selected: 142 islaunch = item.isLaunchFile() 143 isconfig = item.isConfigFile() 144 self.editXmlButton.setEnabled(islaunch or isconfig) 145 self.loadXmlButton.setEnabled(islaunch) 146 self.transferButton.setEnabled(islaunch or isconfig) 147 self.loadXmlAsDefaultButton.setEnabled(islaunch)148150 self.launchlist_proxyModel.setFilterRegExp(QtCore.QRegExp(text, 151 QtCore.Qt.CaseInsensitive, 152 QtCore.QRegExp.Wildcard))153155 ''' 156 Reload the current path. 157 ''' 158 self.launchlist_model.reloadCurrentPath() 159 self.launchlist_model.reloadPackages() 160 self.editXmlButton.setEnabled(False) 161 self.loadXmlButton.setEnabled(False) 162 self.transferButton.setEnabled(False) 163 self.loadXmlAsDefaultButton.setEnabled(False)164166 ''' 167 Opens an XML editor to edit the launch file. 168 ''' 169 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 170 for item in selected: 171 path = self.launchlist_model.expandItem(item.name, item.path, item.id) 172 if not path is None: 173 self.edit_signal.emit([path])174176 ''' 177 Creates a new launch file. 178 ''' 179 # get new file from open dialog, use last path if one exists 180 open_path = self.__current_path 181 if not self.launchlist_model.currentPath is None: 182 open_path = self.launchlist_model.currentPath 183 (fileName, filter) = QtGui.QFileDialog.getSaveFileName(self, 184 "New launch file", 185 open_path, 186 "Config files (*.launch *.yaml);;All files (*)") 187 if fileName: 188 try: 189 (pkg, pkg_path) = package_name(os.path.dirname(fileName)) 190 if pkg is None: 191 WarningMessageBox(QtGui.QMessageBox.Warning, "New File Error", 192 'The new file is not in a ROS package').exec_() 193 return 194 with open(fileName, 'w+') as f: 195 f.write("<launch>\n" 196 " <arg name=\"robot_ns\" default=\"my_robot\"/>\n" 197 " <group ns=\"$(arg robot_ns)\">\n" 198 " <param name=\"tf_prefix\" value=\"$(arg robot_ns)\"/>\n" 199 "\n" 200 " <node pkg=\"my_pkg\" type=\"my_node\" name=\"my_name\" >\n" 201 " <param name=\"capability_group\" value=\"MY_GROUP\"/>\n" 202 " </node>\n" 203 " </group>\n" 204 "</launch>\n" 205 ) 206 self.__current_path = os.path.dirname(fileName) 207 self.launchlist_model.setPath(self.__current_path) 208 self.edit_signal.emit([fileName]) 209 except EnvironmentError as e: 210 WarningMessageBox(QtGui.QMessageBox.Warning, "New File Error", 211 'Error while create a new file', 212 '%s'%e).exec_()213215 (fileName, filter) = QtGui.QFileDialog.getOpenFileName(self, 216 "Load launch file", 217 self.__current_path, 218 "Config files (*.launch);;All files (*)") 219 if fileName: 220 self.__current_path = os.path.dirname(fileName) 221 self.launchlist_model.add2LoadHistory(fileName) 222 self.load_signal.emit(fileName)223225 ''' 226 Emit the signal to copy the selected file to a remote host. 227 ''' 228 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 229 paths = list() 230 for item in selected: 231 path = self.launchlist_model.expandItem(item.name, item.path, item.id) 232 if not path is None: 233 paths.append(path) 234 if paths: 235 self.transfer_signal.emit(paths)236238 ''' 239 Tries to load the selected launch file. The button is only enabled and this 240 method is called, if the button was enabled by on_launch_selection_clicked() 241 ''' 242 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 243 for item in selected: 244 path = self.launchlist_model.expandItem(item.name, item.path, item.id) 245 if not path is None: 246 self.launchlist_model.add2LoadHistory(path) 247 self.load_signal.emit(path)248250 ''' 251 Tries to load the selected launch file as default configuration. The button 252 is only enabled and this method is called, if the button was enabled by 253 on_launch_selection_clicked() 254 ''' 255 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 256 for item in selected: 257 path = self.launchlist_model.expandItem(item.name, item.path, item.id) 258 if not path is None: 259 params = {'Host' : ('string', 'localhost') } 260 dia = ParameterDialog(params) 261 dia.setFilterVisible(False) 262 dia.setWindowTitle('Start node on...') 263 dia.resize(350,120) 264 dia.setFocusField('Host') 265 if dia.exec_(): 266 try: 267 params = dia.getKeywords() 268 host = params['Host'] 269 rospy.loginfo("LOAD the launch file on host %s as default: %s"%(host, path)) 270 self.launchlist_model.add2LoadHistory(path) 271 self.load_as_default_signal.emit(path, host) 272 except Exception, e: 273 WarningMessageBox(QtGui.QMessageBox.Warning, "Load default config error", 274 'Error while parse parameter', 275 '%s'%e).exec_()276 277279 ''' 280 Tries to load the selected launch file as default configuration. The button 281 is only enabled and this method is called, if the button was enabled by 282 on_launch_selection_clicked() 283 ''' 284 key_mod = QtGui.QApplication.keyboardModifiers() 285 if (key_mod & QtCore.Qt.ShiftModifier): 286 self.loadXmlAsDefaultButton.showMenu() 287 else: 288 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 289 for item in selected: 290 path = self.launchlist_model.expandItem(item.name, item.path, item.id) 291 if not path is None: 292 rospy.loginfo("LOAD the launch file as default: %s", path) 293 self.launchlist_model.add2LoadHistory(path) 294 self.load_as_default_signal.emit(path, None)295297 result = [] 298 for index in indexes: 299 if index.column() == 0: 300 model_index = self.launchlist_proxyModel.mapToSource(index) 301 item = self.launchlist_model.itemFromIndex(model_index) 302 if not item is None and isinstance(item, LaunchItem): 303 result.append(item) 304 return result305307 ''' 308 Defines some of shortcuts for navigation/management in launch 309 list view or topics view. 310 ''' 311 key_mod = QtGui.QApplication.keyboardModifiers() 312 if not self.xmlFileView.state() == QtGui.QAbstractItemView.EditingState: 313 # remove history file from list by pressing DEL 314 if event == QtGui.QKeySequence.Delete: 315 selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) 316 for item in selected: 317 if item.path in self.launchlist_model.load_history: 318 self.launchlist_model.removeFromLoadHistory(item.path) 319 self.launchlist_model.reloadCurrentPath() 320 elif not key_mod and event.key() == QtCore.Qt.Key_F4 and self.editXmlButton.isEnabled(): 321 # open selected launch file in xml editor by F4 322 self.on_edit_xml_clicked() 323 elif event == QtGui.QKeySequence.Find: 324 # set focus to filter box for packages 325 self.searchPackageLine.setFocus(QtCore.Qt.ActiveWindowFocusReason) 326 elif event == QtGui.QKeySequence.Paste: 327 # paste files from clipboard 328 self.launchlist_model.paste_from_clipboard() 329 elif event == QtGui.QKeySequence.Copy: 330 # copy the selected items as file paths into clipboard 331 selected = self.xmlFileView.selectionModel().selectedIndexes() 332 indexes = [] 333 for s in selected: 334 indexes.append(self.launchlist_proxyModel.mapToSource(s)) 335 self.launchlist_model.copy_to_clipboard(indexes) 336 if self.searchPackageLine.hasFocus() and event.key() == QtCore.Qt.Key_Escape: 337 # cancel package filtering on pressing ESC 338 self.launchlist_model.show_packages(False) 339 self.searchPackageLine.setText('') 340 self.xmlFileView.setFocus(QtCore.Qt.ActiveWindowFocusReason) 341 QtGui.QDockWidget.keyReleaseEvent(self, event)342344 self.launchlist_model.show_packages(True) 345 QtGui.QLineEdit.focusInEvent(self.searchPackageLine, event)
Home | Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Mon Oct 6 11:14:56 2014 | http://epydoc.sourceforge.net |