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