def reloadPackages(self): ''' Reloads the cached packag list. ''' if not self._fill_packages_thread.isAlive(): self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start()
def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.setWindowTitle('Select Binary') self.verticalLayout = QtGui.QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.content = QtGui.QWidget() self.contentLayout = QtGui.QFormLayout(self.content) self.contentLayout.setVerticalSpacing(0) self.verticalLayout.addWidget(self.content) self.packages = None package_label = QtGui.QLabel("Package:", self.content) self.package_field = QtGui.QComboBox(self.content) self.package_field.setInsertPolicy( QtGui.QComboBox.InsertAlphabetically) self.package_field.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) self.package_field.setEditable(True) self.contentLayout.addRow(package_label, self.package_field) binary_label = QtGui.QLabel("Binary:", self.content) self.binary_field = QtGui.QComboBox(self.content) # self.binary_field.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) self.binary_field.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) self.binary_field.setEditable(True) self.contentLayout.addRow(binary_label, self.binary_field) self.buttonBox = QtGui.QDialogButtonBox(self) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.package_field.setFocus(QtCore.Qt.TabFocusReason) self.package = '' self.binary = '' if self.packages is None: self.package_field.addItems(['packages searching...']) self.package_field.setCurrentIndex(0) self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject) QtCore.QMetaObject.connectSlotsByName(self) self.package_field.activated[str].connect(self.on_package_selected) self.package_field.textChanged.connect(self.on_package_selected)
def __init__(self): ''' Creates a new list model. ''' QtGui.QStandardItemModel.__init__(self) self.setColumnCount(len(LaunchListModel.header)) self.setHorizontalHeaderLabels([label for label, width in LaunchListModel.header]) self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass self.items = [] self.DIR_CACHE = {} self.currentPath = None self.load_history = self._getLoadHistory() self.root_paths = [os.path.normpath(p) for p in os.getenv("ROS_PACKAGE_PATH").split(':')] self._setNewList(self._moveUp(None)) self.__packages = {} self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start()
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Select Binary') self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.content = QWidget() self.contentLayout = QFormLayout(self.content) self.contentLayout.setVerticalSpacing(0) self.verticalLayout.addWidget(self.content) self.packages = None package_label = QLabel("Package:", self.content) self.package_field = QComboBox(self.content) self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically) self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.package_field.setEditable(True) self.contentLayout.addRow(package_label, self.package_field) binary_label = QLabel("Binary:", self.content) self.binary_field = QComboBox(self.content) # self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.binary_field.setEditable(True) self.contentLayout.addRow(binary_label, self.binary_field) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.package_field.setFocus(Qt.TabFocusReason) self.package = '' self.binary = '' if self.packages is None: self.package_field.addItems(['packages searching...']) self.package_field.setCurrentIndex(0) self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) QMetaObject.connectSlotsByName(self) self.package_field.activated[str].connect(self.on_package_selected) if hasattr(self.package_field, "textChanged"): # qt compatibility self.package_field.textChanged.connect(self.on_package_selected) self.binary_field.textChanged.connect(self.on_binary_selected) else: self.package_field.editTextChanged.connect(self.on_package_selected) self.binary_field.editTextChanged.connect(self.on_binary_selected)
class PackageDialog(QtGui.QDialog): def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.setWindowTitle('Select Binary') self.verticalLayout = QtGui.QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.content = QtGui.QWidget() self.contentLayout = QtGui.QFormLayout(self.content) self.contentLayout.setVerticalSpacing(0) self.verticalLayout.addWidget(self.content) self.packages = None package_label = QtGui.QLabel("Package:", self.content) self.package_field = QtGui.QComboBox(self.content) self.package_field.setInsertPolicy( QtGui.QComboBox.InsertAlphabetically) self.package_field.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) self.package_field.setEditable(True) self.contentLayout.addRow(package_label, self.package_field) binary_label = QtGui.QLabel("Binary:", self.content) self.binary_field = QtGui.QComboBox(self.content) # self.binary_field.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) self.binary_field.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)) self.binary_field.setEditable(True) self.contentLayout.addRow(binary_label, self.binary_field) self.buttonBox = QtGui.QDialogButtonBox(self) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.package_field.setFocus(QtCore.Qt.TabFocusReason) self.package = '' self.binary = '' if self.packages is None: self.package_field.addItems(['packages searching...']) self.package_field.setCurrentIndex(0) self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject) QtCore.QMetaObject.connectSlotsByName(self) self.package_field.activated[str].connect(self.on_package_selected) self.package_field.textChanged.connect(self.on_package_selected) def _fill_packages(self, packages): # fill the input fields self.packages = packages packages = packages.keys() packages.sort() self.package_field.clear() self.package_field.clearEditText() self.package_field.addItems(packages) def _getBinaries(self, path): result = {} if os.path.isdir(path): fileList = os.listdir(path) for f in fileList: if f and f[0] != '.' and not f in [ 'build' ] and not f.endswith('.cfg') and not f.endswith('.so'): ret = self._getBinaries(os.path.join(path, f)) result = dict(ret.items() + result.items()) elif os.path.isfile(path) and os.access(path, os.X_OK): # create a selection for binaries return {os.path.basename(path): path} return result def on_package_selected(self, package): self.binary_field.clear() if self.packages and self.packages.has_key(package): self.binary_field.setEnabled(True) path = self.packages[package] binaries = self._getBinaries(path).keys() try: # find binaries in catkin workspace from catkin.find_in_workspaces import find_in_workspaces as catkin_find search_paths = catkin_find(search_dirs=['libexec', 'share'], project=package, first_matching_workspace_only=True) for p in search_paths: binaries += self._getBinaries(p).keys() except: pass binaries = list(set(binaries)) binaries.sort() self.binary_field.addItems(binaries) self.package = package self.binary = binaries[0] if binaries else ''
class LaunchListModel(QtGui.QStandardItemModel): ''' The model to manage the list with launch files. ''' header = [('Name', -1)] '''@ivar: the list with columns C{[(name, width), ...]}''' def __init__(self): ''' Creates a new list model. ''' QtGui.QStandardItemModel.__init__(self) self.setColumnCount(len(LaunchListModel.header)) self.setHorizontalHeaderLabels([label for label, width in LaunchListModel.header]) self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass self.items = [] self.DIR_CACHE = {} self.currentPath = None self.load_history = self._getLoadHistory() self.root_paths = [os.path.normpath(p) for p in os.getenv("ROS_PACKAGE_PATH").split(':')] self._setNewList(self._moveUp(None)) self.__packages = {} self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() def _getRootItems(self): result = list(self.load_history) result.extend(self.root_paths) return result def _fill_packages(self, packages): self.__packages = packages #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%%%%%%%% Overloaded methods %%%%%%%% #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def flags(self, index): ''' @param index: parent of the list @type index: L{PySide.QtCore.QModelIndex} @return: Flag or the requested item @rtype: L{PySide.QtCore.Qt.ItemFlag} @see: U{http://www.pyside.org/docs/pyside-1.0.1/PySide/QtCore/Qt.html} ''' if not index.isValid(): return QtCore.Qt.NoItemFlags try: item = self.itemFromIndex(index) result = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDragEnabled if item.id in [LaunchItem.RECENT_FILE, LaunchItem.LAUNCH_FILE, LaunchItem.CFG_FILE, LaunchItem.FOLDER]: result = result | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled return result except: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%%%%%%%% Drag operation %%%%%%%% #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def mimeTypes(self): return ['text/plain'] def mimeData(self, indexes): mimeData = QtCore.QMimeData() text = '' for index in indexes: if index.isValid(): item = self.itemFromIndex(index) prev = '%s\n'%text if text else '' text = '%sfile://%s'%(prev, item.path) mimeData.setData('text/plain', text) return mimeData #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%%%%%%%% External usage %%%%%%%% #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def reloadPackages(self): ''' Reloads the cached packag list. ''' if not self._fill_packages_thread.isAlive(): self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() def reloadCurrentPath(self): ''' Reloads the current path. ''' # clear the cache for package names try: from common import PACKAGE_CACHE PACKAGE_CACHE.clear() self.DIR_CACHE = {} except: import traceback print traceback.format_exc(2) try: if self.currentPath is None: self._setNewList(self._moveUp(self.currentPath)) else: self._setNewList(self._moveDown(self.currentPath)) except: self._setNewList(self._moveUp(None)) def expandItem(self, path_item, path, id): ''' Returns for the given item and path the file path if this is a file. Otherwise the folder will be expanded and None will be returned. @param path_item: the list item @type path_item: C{str} @param path: the real path of the item @type path: C{str} @return: path of the launch file or None @rtype: C{str @raise Exception if no path to given item was found ''' if path_item == '..': root_path, items = self._moveUp(os.path.dirname(path)) elif os.path.isfile(path): return path elif id == LaunchItem.RECENT_FILE or id == LaunchItem.LAUNCH_FILE: raise Exception("Invalid file path: %s", path) else: root_path, items = self._moveDown(path) self._setNewList((root_path, items)) return None def setPath(self, path): ''' Shows the new path in the launch configuration view. Only if the new path is in ros package paths @param path: new path @type path: C{str} ''' # if self._is_in_ros_packages(path): self._setNewList(self._moveDown(path)) def add2LoadHistory(self, file): try: self.load_history.remove(file) except: pass self.load_history.append(file) try: while len(self.load_history) > nm.settings().launch_history_length: self.load_history.pop(0) except: pass self._storeLoadHistory(self.load_history) # self.reloadCurrentPath() # todo: keep the item selected in list view after the reload the path def removeFromLoadHistory(self, file): try: self.load_history.remove(file) except: pass self._storeLoadHistory(self.load_history) # self.reloadCurrentPath() # todo: keep the item selected in list view after the reload the path def show_packages(self, show): if show: # clear the cache for package names try: items = [] for package, path in self.__packages.items(): items.append((package, path, LaunchItem.PACKAGE)) self._setNewList((self.currentPath if self.currentPath else '', items)) except: import traceback print traceback.format_exc(2) else: self._setNewList(self._moveUp(self.currentPath)) def paste_from_clipboard(self): ''' Copy the file or folder to new position... ''' if QtGui.QApplication.clipboard().mimeData().hasText() and self.currentPath: text = QtGui.QApplication.clipboard().mimeData().text() if text.startswith('file://'): path = text.replace('file://', '') basename = os.path.basename(text) ok = True if os.path.exists(os.path.join(self.currentPath, basename)): basename, ok = QtGui.QInputDialog.getText(None, 'File exists', 'New name (or override):', QtGui.QLineEdit.Normal, basename) if ok and basename: if os.path.isdir(path): shutil.copytree(path, os.path.join(self.currentPath, basename)) elif os.path.isfile(path): shutil.copy2(path, os.path.join(self.currentPath, basename)) self.reloadCurrentPath() def copy_to_clipboard(self, indexes): ''' Copy the selected path to the clipboard ''' mimeData = QtCore.QMimeData() text = '' for index in indexes: if index.isValid(): item = self.itemFromIndex(index) prev = '%s\n'%text if text else '' text = '%sfile://%s'%(prev, item.path) mimeData.setData('text/plain', text) QtGui.QApplication.clipboard().setMimeData(mimeData) #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%%%%%%%% Functionality %%%%%%%% #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def _setNewList(self, (root_path, items)): ''' Sets the list to the given path and insert the items. If the root path is not None the additional item '..' to go up will be inserted. The items parameter is a tupel with three values (the displayed name, the path of the item, the id of the item). @see: L{LaunchListModel._addPathToList()} @param root_path: the root directory @type root_path: C{str} @param items: the list with characterized items @type items: C{[(item, path, id)]} ''' root = self.invisibleRootItem() while root.rowCount(): root.removeRow(0) self.pyqt_workaround.clear() # add new items if not root_path is None: self._addPathToList('..', root_path, LaunchItem.NOTHING) for item_name, item_path, item_id in items: self._addPathToList(item_name, item_path, item_id) self.currentPath = root_path
class PackageDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Select Binary') self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.content = QWidget() self.contentLayout = QFormLayout(self.content) self.contentLayout.setVerticalSpacing(0) self.verticalLayout.addWidget(self.content) self.packages = None package_label = QLabel("Package:", self.content) self.package_field = QComboBox(self.content) self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically) self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.package_field.setEditable(True) self.contentLayout.addRow(package_label, self.package_field) binary_label = QLabel("Binary:", self.content) self.binary_field = QComboBox(self.content) # self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.binary_field.setEditable(True) self.contentLayout.addRow(binary_label, self.binary_field) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.package_field.setFocus(Qt.TabFocusReason) self.package = '' self.binary = '' if self.packages is None: self.package_field.addItems(['packages searching...']) self.package_field.setCurrentIndex(0) self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) QMetaObject.connectSlotsByName(self) self.package_field.activated[str].connect(self.on_package_selected) if hasattr(self.package_field, "textChanged"): # qt compatibility self.package_field.textChanged.connect(self.on_package_selected) self.binary_field.textChanged.connect(self.on_binary_selected) else: self.package_field.editTextChanged.connect(self.on_package_selected) self.binary_field.editTextChanged.connect(self.on_binary_selected) def _fill_packages(self, packages): # fill the input fields self.packages = packages packages = packages.keys() packages.sort() self.package_field.clear() self.package_field.clearEditText() self.package_field.addItems(packages) def _getBinaries(self, path): result = {} if os.path.isdir(path): fileList = os.listdir(path) for f in fileList: if f and f[0] != '.' and f not in ['build'] and not f.endswith('.cfg') and not f.endswith('.so'): ret = self._getBinaries(os.path.join(path, f)) result = dict(ret.items() + result.items()) elif os.path.isfile(path) and os.access(path, os.X_OK): # create a selection for binaries return {os.path.basename(path): path} return result def on_package_selected(self, package): self.binary_field.clear() if self.packages and package in self.packages: self.binary_field.setEnabled(True) path = self.packages[package] binaries = self._getBinaries(path).keys() try: # find binaries in catkin workspace from catkin.find_in_workspaces import find_in_workspaces as catkin_find search_paths = catkin_find(search_dirs=['libexec', 'share'], project=package, first_matching_workspace_only=True) for p in search_paths: binaries += self._getBinaries(p).keys() except: pass binaries = list(set(binaries)) binaries.sort() self.binary_field.addItems(binaries) self.package = package self.binary = self.binary_field.currentText() def on_binary_selected(self, binary): self.binary = binary