~ugocupcic/sr-ros-interface/manipulation

« back to all changes in this revision

Viewing changes to shadow_robot/sr_control_gui/src/sr_control_gui/dock_widgets/robot_and_libraries_dock_widget.py

  • Committer: Ugo Cupcic
  • Date: 2011-05-23 15:44:05 UTC
  • mfrom: (119.1.67 sr-ros-interface)
  • Revision ID: ugo@shadowrobot.com-20110523154405-kwvv543sy9wxehzi
Huge merge from trunk. Lots of changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
 
1
#!/usr/bin/env python
 
2
#
 
3
# Copyright 2011 Shadow Robot Company Ltd.
 
4
#
 
5
# This program is free software: you can redistribute it and/or modify it
 
6
# under the terms of the GNU General Public License as published by the Free
 
7
# Software Foundation, either version 2 of the License, or (at your option)
 
8
# any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful, but WITHOUT
 
11
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
12
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
13
# more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License along
 
16
# with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
#
2
18
import roslib; roslib.load_manifest('sr_control_gui')
3
19
 
4
20
import rospy
17
33
        QtGui.QDialog.__init__(self, parent)
18
34
        self.library = library
19
35
        self.treeitem = treeitem
20
 
        
 
36
 
21
37
        self.setWindowTitle(title)
22
38
        self.setModal(True)
23
39
 
24
40
        dialog_frame = QtGui.QFrame(self)
25
41
        dialog_layout = QtGui.QGridLayout()
26
 
        
 
42
 
27
43
        label_login = QtGui.QLabel(dialog_frame)
28
44
        label_login.setText("Login: ")
29
 
        self.login_input = QtGui.QLineEdit(dialog_frame)    
 
45
        self.login_input = QtGui.QLineEdit(dialog_frame)
30
46
        dialog_layout.addWidget(label_login, 0, 0)
31
 
        dialog_layout.addWidget(self.login_input, 0, 1)    
32
 
        
 
47
        dialog_layout.addWidget(self.login_input, 0, 1)
 
48
 
33
49
        dialog_frame.connect(self.login_input, QtCore.SIGNAL('textChanged(QString)'),
34
50
                             self.login_changed)
35
 
        
 
51
 
36
52
        label_pwd = QtGui.QLabel(dialog_frame)
37
53
        label_pwd.setText("Password: ")
38
54
        self.pwd_input = QtGui.QLineEdit(dialog_frame)
39
55
        self.pwd_input.setEchoMode(QtGui.QLineEdit.Password)
40
56
        dialog_layout.addWidget(label_pwd, 1, 0)
41
57
        dialog_layout.addWidget(self.pwd_input, 1, 1)
42
 
 
 
58
 
43
59
        dialog_frame.connect(self.pwd_input, QtCore.SIGNAL('textChanged(QString)'),
44
60
                             self.pwd_changed)
45
 
        
 
61
 
46
62
        dialog_frame.setLayout(dialog_layout)
47
 
        
48
 
        btn_frame = QtGui.QFrame()   
 
63
 
 
64
        btn_frame = QtGui.QFrame()
49
65
        self.btn_ok = QtGui.QPushButton(btn_frame)
50
66
        self.btn_ok.setText("OK")
51
67
        self.btn_ok.setDisabled(True)
53
69
        btn_cancel = QtGui.QPushButton(btn_frame)
54
70
        btn_cancel.setText("Cancel")
55
71
        self.connect(btn_cancel, QtCore.SIGNAL("clicked()"), self.reject)
56
 
        
 
72
 
57
73
        btn_layout = QtGui.QHBoxLayout()
58
74
        btn_layout.addWidget(self.btn_ok)
59
75
        btn_layout.addWidget(btn_cancel)
60
76
        btn_frame.setLayout(btn_layout)
61
 
        
 
77
 
62
78
        layout = QtGui.QVBoxLayout()
63
79
        layout.addWidget(dialog_frame)
64
80
        layout.addWidget(btn_frame)
65
81
        self.setLayout(layout)
66
82
 
67
83
        self.show()
68
 
    
 
84
 
69
85
    def login_changed(self, login):
70
86
        if login != "":
71
87
            if str(self.pwd_input.text()) != "":
72
88
                self.btn_ok.setEnabled(True)
73
89
                return
74
90
        self.btn_ok.setDisabled(True)
75
 
        
 
91
 
76
92
    def pwd_changed(self, pwd):
77
93
        if pwd != "":
78
94
            if str(self.login_input.text()) != "":
79
95
                self.btn_ok.setEnabled(True)
80
96
                return
81
97
        self.btn_ok.setDisabled(True)
82
 
    
 
98
 
83
99
    def accept(self):
84
100
        cursor = Qt.QCursor()
85
101
        cursor.setShape(QtCore.Qt.WaitCursor)
86
102
        self.setCursor(cursor)
87
 
        
 
103
 
88
104
        login = str(self.login_input.text())
89
105
        pwd = str(self.pwd_input.text())
90
 
        
 
106
 
91
107
        good_pwd = self.library.test_login_pwd(login, pwd)
92
 
        
 
108
 
93
109
        if good_pwd:
94
110
            self.library.login = login
95
111
            self.library.password = pwd
99
115
            rospy.logerr("Wrong password - setting local IP")
100
116
            cursor.setShape(QtCore.Qt.ArrowCursor)
101
117
            self.setCursor(cursor)
102
 
        
 
118
 
103
119
            self.reject()
104
 
        
 
120
 
105
121
        cursor.setShape(QtCore.Qt.ArrowCursor)
106
122
        self.setCursor(cursor)
107
123
        #restarting the timer
108
124
        self.treeitem.timer.start()
109
125
        QtGui.QDialog.accept(self)
110
 
        
 
126
 
111
127
    def reject(self):
112
128
        self.library.set_local_ip()
113
129
        self.treeitem.setData(3, QtCore.Qt.DisplayRole, self.library.hostname)
114
130
        self.treeitem.reboot_computer_action.setDisabled(True)
115
131
        self.treeitem.setIcon(0, QtGui.QIcon(self.library.icon_local_path))
116
 
        
 
132
 
117
133
        QtGui.QDialog.reject(self)
118
134
 
119
135
class LibraryItem(QtGui.QTreeWidgetItem):
129
145
        self.library = library
130
146
        self.parent = parent
131
147
        QtGui.QTreeWidgetItem.__init__(self, data)
132
 
        
 
148
 
133
149
        self.setIcon(1, QtGui.QIcon(self.library.icon_library_path))
134
150
        self.menu = QtGui.QMenu(data[0])
135
 
        
 
151
 
136
152
        self.green = QtGui.QColor(153, 231, 96)
137
153
        self.red = QtGui.QColor(236, 178, 178)
138
154
        self.bright_red = QtGui.QColor(255, 78, 78)
139
155
        self.orange = QtGui.QColor(253, 166, 15)
140
 
        
 
156
 
141
157
        self.start_lib = QtGui.QAction('Start', self.menu)
142
158
        self.menu.connect(self.start_lib, QtCore.SIGNAL('triggered()'), self.start_library)
143
 
        
 
159
 
144
160
        self.stop_lib = QtGui.QAction('Stop', self.menu)
145
161
        self.menu.connect(self.stop_lib, QtCore.SIGNAL('triggered()'), self.stop_library)
146
 
        
 
162
 
147
163
        self.reboot_computer_action = QtGui.QAction('Reboot the computer', self.menu)
148
164
        self.menu.connect(self.reboot_computer_action, QtCore.SIGNAL('triggered()'), self.reboot_computer)
149
 
        
 
165
 
150
166
        self.edit_ip_action = QtGui.QAction('Modify the IP address', self.menu)
151
167
        self.menu.connect(self.edit_ip_action, QtCore.SIGNAL('triggered()'), self.edit_ip)
152
 
        
 
168
 
153
169
        if self.library.is_local:
154
170
            self.reboot_computer_action.setDisabled(True)
155
171
            self.setIcon(0, QtGui.QIcon(self.library.icon_local_path))
156
 
        
 
172
 
157
173
        self.menu.addAction(self.start_lib)
158
174
        self.menu.addAction(self.stop_lib)
159
175
        self.menu.addSeparator()
160
176
        self.menu.addAction(self.reboot_computer_action)
161
177
        self.menu.addSeparator()
162
178
        self.menu.addAction(self.edit_ip_action)
163
 
       
 
179
 
164
180
        self.error_starting_stopping_status = ""
165
181
        self.error_starting_stopping_timer = QtCore.QTimer(parent)
166
182
        parent.connect(self.error_starting_stopping_timer, QtCore.SIGNAL('timeout()'),
167
183
                       self.check_error_starting_stopping)
168
184
        self.error_starting_stopping_timer.setSingleShot(True)
169
185
        self.error_starting_stopping_timer.setInterval(Config.library_timeout * 1000)
170
 
       
 
186
 
171
187
        self.timer = QtCore.QTimer(parent)
172
188
        parent.connect(self.timer, QtCore.SIGNAL('timeout()'), self.refresh_status)
173
189
        self.timer.setInterval(1000 / Config.library_refresh_rate)
174
190
        self.timer.start()
175
 
            
 
191
 
176
192
    def edit_ip(self):
177
193
        self.setFlags(self.flags() | QtCore.Qt.ItemIsEditable)
178
194
        self.parent.editItem(self, 3)
179
 
    
 
195
 
180
196
    def check_error_starting_stopping(self):
181
197
        print "Timeout"
182
198
        self.library.status = "Error"
184
200
        self.setBackgroundColor(2, QtGui.QColor(self.bright_red))
185
201
        self.start_lib.setEnabled(True)
186
202
        self.stop_lib.setEnabled(True)
187
 
            
 
203
 
188
204
    def refresh_status(self):
189
205
        self.library.get_status()
190
206
        current_status = self.library.status
198
214
            self.start_lib.setDisabled(True)
199
215
            self.stop_lib.setDisabled(True)
200
216
            self.setBackgroundColor(2, QtGui.QColor(self.orange))
201
 
            
 
217
 
202
218
        if current_status == "started":
203
219
            if self.error_starting_stopping_timer.isActive():
204
220
                if self.error_starting_stopping_status == "starting":
205
221
                    self.error_starting_stopping_timer.stop()
206
222
            self.start_lib.setDisabled(True)
207
223
            self.stop_lib.setEnabled(True)
208
 
            
 
224
 
209
225
            self.setBackgroundColor(2, QtGui.QColor(self.green))
210
226
        if current_status == "stopped":
211
227
            if self.error_starting_stopping_timer.isActive():
213
229
                    self.error_starting_stopping_timer.stop()
214
230
            self.start_lib.setEnabled(True)
215
231
            self.stop_lib.setDisabled(True)
216
 
            
 
232
 
217
233
            self.setBackgroundColor(2, QtGui.QColor(self.red))
218
 
            
 
234
 
219
235
    def setData(self, column, role, value):
220
236
        """
221
237
        overload the virtual setData method to read the new ip
228
244
                self.change_ip(value)
229
245
            except:
230
246
                return - 1
231
 
    
 
247
 
232
248
    def showContextMenu(self, point):
233
249
        self.menu.exec_(point)
234
250
 
244
260
 
245
261
    def reboot_computer(self):
246
262
        rospy.logerr("reboot not yet implemented")
247
 
    
 
263
 
248
264
    def change_ip(self, new_ip):
249
265
        cursor = Qt.QCursor()
250
266
        cursor.setShape(QtCore.Qt.WaitCursor)
251
267
        self.parent.setCursor(cursor)
252
 
        
 
268
 
253
269
        self.timer.stop()
254
270
        if new_ip == "local":
255
271
            self.library.set_local_ip()
262
278
            self.setIcon(0, QtGui.QIcon(self.library.icon_local_path))
263
279
        else:
264
280
            LoginForm(self.parent, self, self.library.hostname + " login", self.library)
265
 
        
 
281
 
266
282
        cursor.setShape(QtCore.Qt.ArrowCursor)
267
283
        self.parent.setCursor(cursor)
268
 
    
 
284
 
269
285
    def close(self):
270
286
        self.timer.stop()
271
287
        try:
272
288
            self.library.ssh_client.close()
273
289
        except:
274
290
            #the ssh client was already closed. Do nothing
275
 
            nothing = True    
276
 
    
 
291
            nothing = True
 
292
 
277
293
class LibrariesWidget(QtGui.QWidget):
278
294
    """
279
295
    Add the correct library to the libraries dict. And contains the QTreeWidget which will display
281
297
    """
282
298
    def __init__(self, parent, backend):
283
299
        QtGui.QWidget.__init__(self, parent=parent)
284
 
               
 
300
 
285
301
        layout = QtGui.QHBoxLayout()
286
302
 
287
303
        list_frame = QtGui.QFrame(self)
288
304
        listframe_layout = QtGui.QVBoxLayout()
289
 
        
 
305
 
290
306
        self.robot_and_libraries_backend = backend
291
 
        
 
307
 
292
308
        self.robot_and_libraries_backend.add_library(Config.library_shadowhand.name,
293
309
                                                     list_of_nodes=Config.library_shadowhand.list_of_nodes,
294
310
                                                     start_cmd=Config.library_shadowhand.start_cmd,
295
311
                                                     stop_cmd=Config.library_shadowhand.stop_cmd,
296
312
                                                     status_cmd=Config.library_shadowhand.status_cmd,
297
313
                                                     root_path=self.parent().parent().rootPath)
298
 
        
 
314
 
299
315
        self.robot_and_libraries_backend.add_library(Config.library_shadow_arm_hand.name,
300
316
                                                     list_of_nodes=Config.library_shadow_arm_hand.list_of_nodes,
301
317
                                                     start_cmd=Config.library_shadow_arm_hand.start_cmd,
302
318
                                                     stop_cmd=Config.library_shadow_arm_hand.stop_cmd,
303
319
                                                     status_cmd=Config.library_shadow_arm_hand.status_cmd,
304
320
                                                     root_path=self.parent().parent().rootPath)
305
 
        
 
321
 
306
322
        self.robot_and_libraries_backend.add_library(Config.library_cyberglove.name,
307
323
                                                     list_of_nodes=Config.library_cyberglove.list_of_nodes,
308
324
                                                     start_cmd=Config.library_cyberglove.start_cmd,
309
325
                                                     stop_cmd=Config.library_cyberglove.stop_cmd,
310
326
                                                     status_cmd=Config.library_cyberglove.status_cmd,
311
327
                                                     root_path=self.parent().parent().rootPath)
312
 
        
 
328
 
313
329
        self.robot_and_libraries_backend.add_library(Config.library_cyberglove_remapper.name,
314
330
                                                     list_of_nodes=Config.library_cyberglove_remapper.list_of_nodes,
315
331
                                                     start_cmd=Config.library_cyberglove_remapper.start_cmd,
316
332
                                                     stop_cmd=Config.library_cyberglove_remapper.stop_cmd,
317
333
                                                     status_cmd=Config.library_cyberglove_remapper.status_cmd,
318
334
                                                     root_path=self.parent().parent().rootPath)
319
 
        
 
335
 
320
336
        self.robot_and_libraries_backend.add_robot(Config.robot_code.name,
321
337
                                                   root_path=self.parent().parent().rootPath)
322
338
 
323
339
        self.tree = QtGui.QTreeWidget()
324
340
        self.tree.setEditTriggers(Qt.QAbstractItemView.DoubleClicked)
325
 
        
 
341
 
326
342
        self.tree.setHeaderLabels(["", "ROS Nodes / Robot Code", "Status", "Computer", "Info"])
327
 
        
 
343
 
328
344
        self.items = []
329
 
        
 
345
 
330
346
        for lib in self.robot_and_libraries_backend.libraries.values():
331
347
            self.items.append(LibraryItem(lib, self.tree))
332
 
        
 
348
 
333
349
        self.tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
334
350
        self.connect(self.tree,
335
351
                     QtCore.SIGNAL("customContextMenuRequested(const QPoint &)"),
336
 
                     self.showContextMenu) 
337
 
                
 
352
                     self.showContextMenu)
 
353
 
338
354
        self.connect(self.tree, QtCore.SIGNAL('itemDoubleClicked (QTreeWidgetItem *, int)'),
339
355
                     self.edit_ip)
340
356
        for item in self.items:
341
357
            self.tree.addTopLevelItem(item)
342
358
        listframe_layout.addWidget(self.tree)
343
 
        
 
359
 
344
360
        self.tree.resizeColumnToContents(0)
345
361
        self.tree.resizeColumnToContents(1)
346
362
        self.tree.resizeColumnToContents(4)
347
363
        #don't resize col 2 and 3 as they contain dynamic content
348
 
        
 
364
 
349
365
        list_frame.setLayout(listframe_layout)
350
366
 
351
367
        layout.addWidget(list_frame)
353
369
 
354
370
    def edit_ip(self, item, value):
355
371
        item.edit_ip()
356
 
    
 
372
 
357
373
    def showContextMenu(self, point):
358
374
        item = self.tree.itemAt(point)
359
375
        if item == None:
361
377
        point.setY(point.y() + 30)
362
378
        point = self.tree.mapToGlobal(point)
363
379
        item.showContextMenu(point)
364
 
    
 
380
 
365
381
    def close(self):
366
382
        for item in self.items:
367
383
            item.close()
368
 
            
 
384
 
369
385
        QtGui.QWidget.close(self)
370
 
        
 
386
 
371
387
class RobotsWidget(QtGui.QWidget):
372
388
    def __init__(self, parent):
373
389
        QtGui.QWidget.__init__(self, parent=parent)
374
390
        layout = QtGui.QVBoxLayout()
375
391
        frame = QtGui.QFrame(self)
376
 
        
 
392
 
377
393
        layout.addWidget(frame)
378
394
        self.setLayout(layout)
379
395
 
383
399
    """
384
400
    def __init__(self, parent, backend):
385
401
        GenericDockWidget.__init__(self, parent=parent)
386
 
        
 
402
 
387
403
        frame = QtGui.QFrame()
388
404
        layout = QtGui.QHBoxLayout()
389
 
        
 
405
 
390
406
        libraries = LibrariesWidget(self, backend)
391
407
        robots = RobotsWidget(self)
392
 
        
 
408
 
393
409
        layout.addWidget(libraries)
394
410
        layout.addWidget(robots)
395
411
 
396
412
        frame.setLayout(layout)
397
413
        self.setWidget(frame)
398
 
        
399
 
        
400
 
    
 
414
 
 
415
 
 
416