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 threading
34 from python_qt_binding import QtCore
35 from python_qt_binding import QtGui
36
37 import rospy
38
39 import node_manager_fkie as nm
40 from detailed_msg_box import WarningMessageBox, DetailedError
41
43 '''
44 request: AuthenticationRequest
45 '''
46 - def __init__(self, request, method, args):
47 Exception.__init__(self)
48 self.method = method
49 self.request = request
50 self.args = args
51
53 return "InteractionNeededError"
54
55
57
58 - def __init__(self, progress_frame, progress_bar, progress_cancel_button):
59 QtCore.QObject.__init__(self)
60 self.__ignore_err_list = []
61 self.__progress_queue = []
62 self.__running = False
63 self._progress_frame = progress_frame
64 self._progress_bar = progress_bar
65 self._progress_cancel_button = progress_cancel_button
66 progress_frame.setVisible(False)
67 progress_cancel_button.clicked.connect(self._on_progress_canceled)
68
70 try:
71 val = self._progress_bar.value()
72 if val < len(self.__progress_queue):
73 print " Shutdown progress queue..."
74 thread = self.__progress_queue[val]
75 self.__progress_queue = []
76 thread.join(3)
77 print " Progress queue is off!"
78 except:
79 pass
80
81
82 - def add2queue(self, id, descr, target=None, args=()):
89
91 if not self.__running and self.__progress_queue:
92 self._progress_frame.setVisible(True)
93 self.__running = True
94 self._progress_bar.setToolTip(self.__progress_queue[0].descr)
95 dscr_len = self._progress_bar.size().width()/10
96 self._progress_bar.setFormat(''.join(['%v/%m - ', self.__progress_queue[0].descr[0:dscr_len]]))
97 self._progress_bar.setValue(0)
98 self.__progress_queue[0].start()
99
101 return len(self.__progress_queue)
102
104 '''
105 Searches the current and planed threads for given id and returns `True` if
106 one is found.
107 '''
108 for th in self.__progress_queue:
109 if th.id() == id:
110 return True
111 return False
112
114 try:
115 val = self._progress_bar.value()
116
117 if id == self.__progress_queue[val].id():
118 val = val + 1
119 th = self.__progress_queue[val]
120 self._progress_bar.setToolTip(th.descr)
121 dscr_len = self._progress_bar.size().width()/10
122 self._progress_bar.setFormat(''.join(['%v/%m - ', th.descr[0:dscr_len]]))
123 self.__progress_queue[val].start()
124 self._progress_bar.setValue(val)
125
126 except:
127
128 for thread in self.__progress_queue:
129 thread.join(1)
130 self._progress_frame.setVisible(False)
131 self.__running = False
132
133 self.__progress_queue = []
134
135
137 if detailed_msg in self.__ignore_err_list:
138 self._progress_thread_finished(id)
139 return
140 btns = (QtGui.QMessageBox.Ignore)
141 if len(self.__progress_queue) > 1:
142 btns = (QtGui.QMessageBox.Ignore|QtGui.QMessageBox.Abort)
143 res = WarningMessageBox(QtGui.QMessageBox.Warning, title, msg, detailed_msg,
144 buttons=btns ).exec_()
145 if res == QtGui.QMessageBox.Abort:
146 self.__progress_queue = []
147 self._progress_frame.setVisible(False)
148 self.__running = False
149 else:
150 if res == 1 or res == 0:
151 self.__ignore_err_list.append(detailed_msg)
152 self._progress_thread_finished(id)
153
155 try:
156
157 if self.__progress_queue:
158 try:
159 self.__progress_queue[self._progress_bar.value()].finished_signal.disconnect(self._progress_thread_finished)
160 self.__progress_queue[self._progress_bar.value()].error_signal.disconnect(self._progress_thread_error)
161 self.__progress_queue[self._progress_bar.value()].request_interact_signal.disconnect(self._on_request_interact)
162
163 except:
164
165 pass
166 self.__progress_queue = []
167 self._progress_frame.setVisible(False)
168 self.__running = False
169 except:
170 import traceback
171 print traceback.format_exc()
172
174 '''
175 If the interaction of the user is needed a message dialog must be exceuted
176 in the main Qt thread. The requests are done by different request exceptinos.
177 These are handled by this method.
178 '''
179 if isinstance(req.request, nm.AuthenticationRequest):
180 res, user, pw = nm.ssh()._requestPW(req.request.user, req.request.host)
181 if not res:
182 self._on_progress_canceled()
183 return
184 pt = ProgressThread(id, descr, req.method, (req.args+(user, pw)))
185 pt.finished_signal.connect(self._progress_thread_finished)
186 pt.error_signal.connect(self._progress_thread_error)
187 pt.request_interact_signal.connect(self._on_request_interact)
188 pt.start()
189 elif isinstance(req.request, nm.ScreenSelectionRequest):
190 from select_dialog import SelectDialog
191 items, ok = SelectDialog.getValue('Show screen', '', req.request.choices.keys(), False)
192 if not items:
193 self._progress_thread_finished(id)
194 return
195 res = [req.request.choices[i] for i in items]
196 pt = ProgressThread(id, descr, req.method, (req.args+(res,)))
197 pt.finished_signal.connect(self._progress_thread_finished)
198 pt.error_signal.connect(self._progress_thread_error)
199 pt.request_interact_signal.connect(self._on_request_interact)
200 pt.start()
201 elif isinstance(req.request, nm.BinarySelectionRequest):
202 from select_dialog import SelectDialog
203 items, ok = SelectDialog.getValue('Multiple executables', '', req.request.choices, True)
204 if not items:
205 self._progress_thread_finished(id)
206 return
207 res = items[0]
208 pt = ProgressThread(id, descr, req.method, (req.args+(res,)))
209 pt.finished_signal.connect(self._progress_thread_finished)
210 pt.error_signal.connect(self._progress_thread_error)
211 pt.request_interact_signal.connect(self._on_request_interact)
212 pt.start()
213 elif isinstance(req.request, nm.LaunchArgsSelectionRequest):
214 from parameter_dialog import ParameterDialog
215 inputDia = ParameterDialog(req.request.args_dict)
216 inputDia.setFilterVisible(False)
217 inputDia.setWindowTitle(''.join(['Enter the argv for ', req.request.launchfile]))
218 if inputDia.exec_():
219 params = inputDia.getKeywords()
220 argv = []
221 for p,v in params.items():
222 if v:
223 argv.append(''.join([p, ':=', v]))
224 res = argv
225 pt = ProgressThread(id, descr, req.method, (req.args+(argv,)))
226 pt.finished_signal.connect(self._progress_thread_finished)
227 pt.error_signal.connect(self._progress_thread_error)
228 pt.request_interact_signal.connect(self._on_request_interact)
229 pt.start()
230 else:
231 self._progress_thread_finished(id)
232 return
233
234
235
237 '''
238 A thread to execute a method in a thread.
239 '''
240 finished_signal = QtCore.Signal(str)
241 '''
242 @ivar: finished_signal is a signal, which is emitted, if the thread is finished.
243 '''
244
245 error_signal = QtCore.Signal(str, str, str, str)
246 '''
247 @ivar: error_signal is a signal (id, title, error message, detailed error message), which is emitted,
248 if an error while run of the thread was occurred.
249 '''
250
251 request_interact_signal = QtCore.Signal(str, str, InteractionNeededError)
252
253 - def __init__(self, id, descr='', target=None, args=()):
254 QtCore.QObject.__init__(self)
255 threading.Thread.__init__(self)
256 self._id = id
257 self.descr = descr
258 self._target = target
259 self._args = args
260 self.setDaemon(True)
261
264
266 '''
267 '''
268 try:
269 if not self._target is None:
270
271
272
273 if 'pqid' in self._target.func_code.co_varnames:
274 self._target(*self._args, pqid=self._id)
275 else:
276 self._target(*self._args)
277
278 self.finished_signal.emit(self._id)
279 else:
280 self.error_signal.emit(self._id, 'No target specified')
281 except InteractionNeededError as e:
282 self.request_interact_signal.emit(self._id, self.descr, e)
283 except DetailedError as e:
284 self.error_signal.emit(self._id, e.title, e.value, e.detailed_text)
285 except:
286 import traceback
287
288 formatted_lines = traceback.format_exc().splitlines()
289 last_line = formatted_lines[-1]
290 index = 1
291 while not last_line and len(formatted_lines) > index:
292 index += 1
293 last_line = formatted_lines[-index]
294 rospy.logwarn("%s failed:\n\t%s", str(self.descr), last_line)
295 self.error_signal.emit(self._id, 'Progress Job Error', str(self.descr)+" failed:\n"+last_line, traceback.format_exc())
296