1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import os
34 import sys
35
36 from PySide import QtCore
37 from PySide import QtGui
38
39 import node_manager_fkie as nm
40 from launch_config import LaunchConfig
41
43 '''
44 The model to manage the files with launch files.
45 '''
46
47 NOT_FOUND = -1
48 NOTHING = 0
49 RECENT_FILE = 1
50 LAUNCH_FILE = 2
51 FOLDER = 3
52 PACKAGE = 4
53 STACK = 5
54
55 RECENT_LENGTH = 5
56
58 '''
59 Creates a new list model. Loads the required icons.
60 '''
61 QtCore.QAbstractListModel.__init__(self)
62 self.icons = {LaunchListModel.FOLDER : QtGui.QIcon(":/icons/crystal_clear_folder.png"),
63 LaunchListModel.STACK : QtGui.QIcon(":/icons/crystal_clear_stack.png"),
64 LaunchListModel.PACKAGE : QtGui.QIcon(":/icons/crystal_clear_package.png"),
65 LaunchListModel.LAUNCH_FILE : QtGui.QIcon(":/icons/crystal_clear_launch_file.png"),
66 LaunchListModel.RECENT_FILE : QtGui.QIcon(":/icons/crystal_clear_launch_file_recent.png")}
67 self.items = []
68 self.currentPath = None
69 self.load_history = self._getLoadHistory()
70 self.root_paths = [os.path.normpath(p) for p in os.getenv("ROS_PACKAGE_PATH").split(':')]
71 self._setNewList(self._moveUp(None))
72
74 result = list(self.load_history)
75 result[len(result):] = self.root_paths
76 return result
77
78
79
80
81
82 - def rowCount(self, parent=QtCore.QModelIndex()):
83 '''
84 Tell the view how many rows we have present in our data.
85 @param parent: parent of the list
86 @type parent: L{QtCore.QModelIndex}
87 '''
88 return len(self.items)
89
90 - def data(self, index, role=QtCore.Qt.DisplayRole):
91 '''
92 The view asks us for all sorts of information about our data...
93 @param index: parent of the list
94 @type index: L{QtCore.QModelIndex}
95 @param role: the art of the data
96 @type role: L{QtCore.Qt.DisplayRole}
97 @see: U{http://www.pyside.org/docs/pyside-1.0.1/PySide/QtCore/Qt.html}
98 '''
99 if role == QtCore.Qt.DisplayRole:
100
101 pathItem, path, pathId = self.items[index.row()]
102 if pathId == LaunchListModel.RECENT_FILE:
103 return ''.join([pathItem, ' [', str(LaunchConfig.packageName(os.path.dirname(path))[0]), ']']).decode(sys.getfilesystemencoding())
104 else:
105 return pathItem
106 elif role == QtCore.Qt.ToolTipRole:
107
108 pathItem, path, pathId = self.items[index.row()]
109 return path
110 elif role == QtCore.Qt.DecorationRole:
111
112 pathItem, path, pathId = self.items[index.row()]
113
114 if pathId > LaunchListModel.NOTHING and self.icons.has_key(pathId):
115 return self.icons[pathId]
116 return None
117 else:
118
119 return None
120
122 '''
123 Make the only selectable
124 @param index: parent of the list
125 @type index: L{QtCore.QModelIndex}
126 @return: Flag or the requestet item
127 @rtype: L{PySide.QtCore.Qt.ItemFlag}
128 @see: U{http://www.pyside.org/docs/pyside-1.0.1/PySide/QtCore/Qt.html}
129 '''
130 return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
131
132
133
134
135
136
138 '''
139 Reloads the current path.
140 '''
141 if self.currentPath is None:
142 self._setNewList(self._moveUp(self.currentPath))
143 else:
144 self._setNewList(self._moveDown(self.currentPath))
145
147 '''
148 Tests for the given row whether it is a launch file or not.
149 @return: C{True} if it is a launch file
150 @rtype: C{boolean}
151 '''
152 if row >= 0 and row < len(self.items):
153 pathItem, path, pathId = self.items[row]
154 return not path is None and os.path.isfile(path) and path.endswith('.launch')
155 return False
156
158 '''
159 Returns for the given item the file path if this is a file. Otherwise the
160 folder will be expanded and None will be returned.
161 @param item: the list item
162 @type item: C{str}
163 @return: path of the launch file or None
164 @rtype: C{str} or C{None}
165 '''
166 for pathItem, path, id in self.items:
167 if item == pathItem:
168 if item == '..':
169 root_path, items = self._moveUp(os.path.dirname(path))
170 elif os.path.isfile(path):
171 return path
172 else:
173 root_path, items = self._moveDown(path)
174 self._setNewList((root_path, items))
175 return None
176
177
179 '''
180 Shows the new path in the launch configuration view. Only if the new path
181 is in ros package paths
182 @param path: new path
183 @type path: C{str}
184 '''
185 if self._is_in_ros_packages(path):
186 self._setNewList(self._moveDown(path))
187
188 - def add2LoadHistory(self, file):
189 try:
190 self.load_history.remove(file)
191 except:
192 pass
193 self.load_history.append(file)
194 if len(self.load_history) > self.RECENT_LENGTH:
195 self.load_history.pop(0)
196 self._storeLoadHistory(self.load_history)
197
198
199
200
201
203 '''
204 Sets the list to the given path and insert the items. If the root path is not
205 None the additional item '..' to go up will be inserted. The items parameter
206 is a tupel with three values (the displayed name, the path of the item, the id
207 of the item).
208 @see: L{LaunchListModel._addPathToList()}
209 @param root_path: the root directory
210 @type root_path: C{str}
211 @param items: the list with characterized items
212 @type items: C{[(item, path, id)]}
213 '''
214 self.beginRemoveRows(QtCore.QModelIndex(), 0, len(self.items))
215 del self.items[:]
216 self.endRemoveRows()
217
218 if not root_path is None:
219 self._addPathToList('..', root_path, LaunchListModel.NOTHING)
220 for item_name, item_path, item_id in items:
221 self._addPathToList(item_name, item_path, item_id)
222 self.currentPath = root_path
223
225 '''
226 Test whether the given path is in ROS_PACKAGE_PATH.
227 @return: C{True}, if the path is in the ROS_PACKAGE_PATH
228 @rtype: C{boolean}
229 '''
230 for p in self.root_paths:
231 if path.startswith(p):
232 return True
233 return False
234
236 '''
237 Inserts the given item in the list model.
238 @param item: the displayed name
239 @type item: C{str}
240 @param path: the path of the item
241 @type path: C{str}
242 @param path_id: the id of the item, which represents whether it is a file, package or stack.
243 @type path_id: C{constants of LaunchListModel}
244 '''
245 if item is None or path is None or path_id == LaunchListModel.NOT_FOUND:
246 return False
247 if (path_id != LaunchListModel.NOT_FOUND):
248
249 for index, (i, p, id) in enumerate(self.items):
250 launch_file_cmp = (path_id == LaunchListModel.RECENT_FILE and id == LaunchListModel.LAUNCH_FILE and i > item)
251 if launch_file_cmp or (id == path_id and i > item):
252 self.beginInsertRows(QtCore.QModelIndex(), index, index)
253 self.items.insert(index, (item, path, path_id))
254 self.endInsertRows()
255 return True
256 self.beginInsertRows(QtCore.QModelIndex(), len(self.items), len(self.items))
257 self.items.append((item, path, path_id))
258 self.endInsertRows()
259 return True
260 return False
261
263 '''
264 Determines the id of the given path
265 @return: the id represents whether it is a file, package or stack
266 @rtype: C{constants of LaunchListModel}
267 '''
268 if os.path.basename(path)[0] != '.':
269 if path in self.load_history:
270 return LaunchListModel.RECENT_FILE
271 elif os.path.isfile(path):
272 if (path.endswith('.launch')):
273 return LaunchListModel.LAUNCH_FILE
274 elif os.path.isdir(path):
275 fileList = os.listdir(path)
276 if self._containsLaunches(path):
277 if 'stack.xml' in fileList:
278 return LaunchListModel.STACK
279 elif 'manifest.xml' in fileList:
280 return LaunchListModel.PACKAGE
281 else:
282 return LaunchListModel.FOLDER
283 return LaunchListModel.NOT_FOUND
284
286 '''
287 Moves recursively down in the path tree and searches for a launch file. If
288 one is found True will be returned.
289 @return: C{True} if the path contains a launch file.
290 @rtype: C{boolean}
291 '''
292 fileList = os.listdir(path)
293 for file in fileList:
294 if os.path.isfile(''.join([path, '/', file])) and file.endswith('.launch'):
295 return True
296 for file in fileList:
297 if os.path.isdir(''.join([path, '/', file])):
298 if self._containsLaunches(''.join([path, '/', file])):
299 return True
300 return False
301
302
304 '''
305 Moves recursively down in the path tree until the current path contains a
306 launch file.
307 @return: tupel of (root_path, items)
308 @rtype: C{tupel of (root_path, items)}
309 @see: L{LaunchListModel._setNewList()}
310 '''
311 result_list = []
312 dirlist = os.listdir(path)
313 for file in dirlist:
314 item = os.path.normpath(''.join([path, '/', file]))
315 pathItem = os.path.basename(item)
316 pathId = self._identifyPath(item)
317 if (pathId != LaunchListModel.NOT_FOUND):
318 result_list.append((pathItem, item, pathId))
319 if len(result_list) == 1 and not os.path.isfile(result_list[0][1]):
320 return self._moveDown(result_list[0][1])
321 return path, result_list
322
324 '''
325 Moves recursively up in the path tree until the current path contains a
326 launch file or the root path defined by ROS_PACKAGES_PATH is reached.
327 @return: tupel of (root_path, items)
328 @rtype: C{tupel of (root_path, items)}
329 @see: L{LaunchListModel._setNewList()}
330 '''
331 result_list = []
332 if path is None or not self._is_in_ros_packages(path):
333 dirlist = self._getRootItems()
334 path = None
335 else:
336 dirlist = os.listdir(path)
337 for file in dirlist:
338 item = os.path.normpath(''.join([path, '/', file])) if not path is None else file
339 pathItem = os.path.basename(item)
340 pathId = self._identifyPath(item)
341 if (pathId != LaunchListModel.NOT_FOUND):
342 result_list.append((pathItem, item, pathId))
343 if not path is None and len(result_list) == 1 and not os.path.isfile(result_list[0][1]):
344 return self._moveUp(os.path.dirname(path))
345 else:
346 self.currentPath = None
347 return path, result_list
348
349 - def _getLoadHistory(self):
350 '''
351 Read the history of the recently loaded files from the file stored in ROS_HOME path.
352 @return: the list with file names
353 @rtype: C{[str]}
354 '''
355 result = list()
356 historyFile = ''.join([nm.CFG_PATH, 'launch.history'])
357 if os.path.isfile(historyFile):
358 with open(historyFile, 'r') as f:
359 line = f.readline()
360 while line:
361 if line:
362 result.append(line.strip())
363 line = f.readline()
364 f.closed
365 return result
366
367 - def _storeLoadHistory(self, files):
368 '''
369 Saves the list of recently loaded files to history. The existing history will be replaced!
370 @param files: the list with filenames
371 @type files: C{[str]}
372 '''
373 if not os.path.isdir(nm.CFG_PATH):
374 os.makedirs(nm.CFG_PATH)
375 with open(''.join([nm.CFG_PATH, 'launch.history']), 'w') as f:
376 for files in files:
377 f.write(''.join([files, '\n']))
378 f.closed
379