24 from roslib.packages
import get_pkg_dir
25 from xml.etree
import ElementTree
30 from python_qt_binding
import loadUi
32 from airbus_pyqt_extend.QtAgiCore
import get_pkg_dir_from_prefix
34 from account
import User, \
38 GUserAccountCommunicate
40 from plugin.plugin_provider
import PluginProvider, PluginsGroup
41 from widget.widget_provider
import WidgetProvider
43 from alarm.alarm
import AlarmCategory
45 from pkg_dir
import airbus_cobot_gui_dir, resources_dir
46 from exception
import CobotGuiException
47 from emergency
import EmergencyStopButton, EmergencyStopState
53 from std_msgs.msg
import String
58 QSplashScreen.__init__(self)
64 background = QPixmap(
resources_dir(
'icons',
'wellcome_background.png'))
65 background = background.scaled(600, 400,
67 Qt.SmoothTransformation)
68 self.setPixmap(background)
70 self.loading_progess.setText(
"Loading ...")
77 self.loading_progess.setText(
"Loading %s ..."%txt)
84 """! CobotGuiMain class inherit QWidget.
85 This class setup all graphics components difinit on your config file:
86 - Setup default rules : Language, size, account, ...
87 - Setup dashboard : load widgets on dashboard registered in section <dashboard>,
88 - Setup launchers : load plugins on launchers registered in section <launcher>,
89 - Setup footer : load widgets on footer registered in section <footer>.
94 @param config: Config file (*.xml).
97 QWidget.__init__(self)
99 self.setAttribute(Qt.WA_AcceptTouchEvents)
108 loadUi(ui_file, self)
112 SIGNAL(
"emergencyStopStatusChanged"),
132 trUtf8.translate.connect(self.control_mode_widget.retranslate)
142 logo = QPixmap(
resources_dir(
'icons',
'logo_airbus_group.png'))
143 logo = logo.scaled(self.logo_label.width()-10,
144 self.logo_label.height()-10,
146 Qt.SmoothTransformation)
147 self.logo_label.setPixmap(logo)
150 self.default_plugin._get_launcher().click()
153 self.control_mode_widget.set_default_mode(ControlMode.AUTOMATIC)
155 self.control_mode_widget.set_default_mode(ControlMode.MANUAL)
157 rospy.logwarn(
'Unknow default-mode="%s"'%default_mode)
158 self.control_mode_widget.set_default_mode(ControlMode.AUTOMATIC)
161 """! Parser xml configuration file.
162 @param config_xml: airbus_cobot_gui configuration path.
163 @type config_xml: string.
167 if not os.path.isfile(config_xml):
168 raise CobotGuiException(
'Config file "%s" not found !'%config_xml)
171 tree = ElementTree.parse(config_xml)
174 language = tree.getroot().find(
'translate').attrib[
'type'].lower()
177 if not os.path.isfile(lng_dir):
178 rospy.logerr(
'Translator from language "%s" could not be found !'%language)
181 trUtf8.load(language, lng_dir)
184 node_window = tree.getroot().find(
'window')
187 self.
show_mode = node_window.attrib[
'display-mode'].lower()
190 for node
in node_window:
191 if node.tag ==
'default-size':
192 width = int(node[0].text)
193 height = int(node[1].text)
194 self.resize(width, height)
195 elif node.tag ==
'dashboard':
197 elif node.tag ==
'launcher':
199 elif node.tag ==
'footer':
202 rospy.logwarn(
'Invalid tag name from "%s" !'%node.tag)
208 self.connect(GUserAccountCommunicate,
209 SIGNAL(
'userAccountChanged'),
213 application_mode = tree.getroot().attrib[
'mode'].lower()
214 if application_mode ==
'dev' or application_mode ==
'debug':
215 GUserAccountCommunicate.update(User(
'Airbus Group', Privilege.EXPERT))
218 GUserAccountCommunicate.update(User())
219 login = LoginDialog(self)
220 QTimer.singleShot(500, login.show)
225 self.connect(GUserAccountCommunicate,
226 SIGNAL(
'userAccountChanged'),
227 widget.userChangedEvent)
230 SIGNAL(
'controlModeChanged'),
231 widget.controlModeChangedEvent)
234 SIGNAL(
"emergencyStopStatusChanged"),
235 widget.emergencyStoppedEvent)
237 trUtf8.translate.connect(widget.retranslateEvent)
243 self.connect(plugin._launcher,
248 SIGNAL(
"emergencyStopStatusChanged"),
249 plugin.emergencyStoppedEvent)
251 self.connect(GUserAccountCommunicate,
252 SIGNAL(
'userAccountChanged'),
256 SIGNAL(
'controlModeChanged'),
257 plugin.controlModeChangedEvent)
259 trUtf8.translate.connect(plugin.retranslateEvent)
262 """! Setup all widgets on dashbord registered on config file.
263 @param tree: node dashbord.
264 @type tree: ElementTree.
268 central_layout = QHBoxLayout(self.dashboard_widget)
269 central_layout.setContentsMargins(5, 5, 5, 5)
270 central_layout.setSpacing(20)
272 my_board_left = QHBoxLayout()
273 my_board_left.setSpacing(20)
275 central_layout.addLayout(my_board_left)
277 spacer = QSpacerItem(40, 20,
278 QSizePolicy.Expanding,
280 central_layout.addItem(spacer)
282 my_board_right = QHBoxLayout()
283 my_board_right.setSpacing(20)
286 central_layout.addLayout(my_board_right)
289 if node.tag ==
'fixed-height':
292 elif node.tag ==
'widgets':
294 register_dir = node.attrib[
'src']
295 register_dir = get_pkg_dir_from_prefix(register_dir)
297 if not os.path.isfile(register_dir):
298 rospy.logerr(
'widgets register file "%s" not found !'%register_dir)
301 widget_provider = WidgetProvider(register_dir)
304 if child.tag ==
'widget':
306 self._splash.update(child.attrib[
'name'])
309 pkg, xml = widget_provider.get_widget_registered(child.attrib[
'name'])
310 widget = widget_provider.load(pkg, xml)
311 widget.retranslateEvent()
312 self._widgets_list.append(widget)
313 except Exception
as e:
314 rospy.logerr(
'WidgetProvider::load(%s) raised with exception %s !'
315 %(child.attrib[
'name'],str(e)))
318 if child.attrib[
'position'] ==
'left':
319 my_board_left.addWidget(widget.get_widget())
321 my_board_right.addWidget(widget.get_widget())
327 my_board_right.addWidget(UserAccountsWidget())
331 translator_widget = TranslatorWidget()
332 self._widgets_list.append(translator_widget)
333 my_board_right.addWidget(translator_widget.get_widget())
336 """! Setup buttons plugins on launcher.
337 @param tree: node launcher.
338 @type tree: ElementTree.
342 self._launcher_layout.setContentsMargins(10, 20, 10, 20)
343 self._launcher_layout.setSpacing(20)
344 self._launcher_layout.setSizeConstraint(QLayout.SetMaximumSize)
349 if node.tag ==
'fixed-width':
352 elif node.tag ==
'plugins':
354 register_dir = node.attrib[
'src']
355 register_dir = get_pkg_dir_from_prefix(register_dir)
357 if not os.path.isfile(register_dir):
358 rospy.logerr(
'Plugins register file "%s" not found !'%register_dir)
361 plugin_provider = PluginProvider(register_dir)
365 if child.tag ==
'plugin':
367 self._splash.update(child.attrib[
'name'])
371 plugin = plugin_provider.load(child, child.attrib[
'name'])
372 plugin.retranslateEvent()
374 if child.attrib[
'name'] == tree.attrib[
'default-view']:
377 self._plugins_list.append(plugin)
378 self._launcher_layout.addWidget(plugin._get_launcher())
380 except Exception
as e:
381 rospy.logerr(
'Load plugin "%s" raised with execption "%s"'
382 %(child.attrib[
'name'], str(e)))
383 elif child.tag ==
'group':
385 plugins_group = PluginsGroup(self,
386 child.attrib[
'name'],
387 child.attrib[
'icon'])
391 self._splash.update(p.attrib[
'name'])
395 plugin = plugin_provider.load(p, p.attrib[
'name'])
396 plugin.retranslateEvent()
397 self._plugins_list.append(plugin)
398 plugins_group.add(plugin._get_launcher())
400 if p.attrib[
'name'] == tree.attrib[
'default-view']:
403 except Exception
as e:
404 rospy.logerr(
'Load plugin "%s" raised with execption "%s"'
405 %(p.attrib[
'name'], str(e)))
407 self._plugins_group_list.append(plugins_group)
408 self._launcher_layout.addWidget(plugins_group)
414 launcher_button = plugin._get_launcher()
415 launcher_button.setIconSize(icon_size)
418 launcher.setIconSize(icon_size)
419 launcher.resizeLaunchers(icon_size)
421 spacer = QSpacerItem(20, 10,
422 QSizePolicy.Expanding,
423 QSizePolicy.Expanding)
424 self._launcher_layout.addItem(spacer)
426 self._emergency_stop.setIconSize(icon_size)
430 """! Find and return plugin selected by user.
431 @param sender_id: launcher id.
432 @type sender_id: String.
434 @return plugin: plugin ui.
435 @type plugin: CobotUiPlugin.
439 launcher = plugin._get_launcher()
440 if launcher.objectName() == sender_id:
446 """! Display plugin on viewer, function called when user select launcher.
451 self._current_plugin.backgroundEvent()
454 b_sender = self.sender()
459 self.viewer_widget.takeWidget()
461 launcher = self._current_plugin._get_launcher()
463 self.viewer_widget.setWidget(self._current_plugin.get_widget())
466 self._current_plugin.foregroundEvent()
469 rospy.logerr(
'Invalid launcher id "%s"'%b_sender.objectName())
473 @param tree: node footer.
474 @type tree: ElementTree.
477 from footer
import Footer_v2
482 if node.tag ==
'maximum-height':
483 self.footer_ui.set_maximum_height(int(node.text))
484 elif node.tag ==
'widgets':
486 register_dir = node.attrib[
'src']
487 register_dir = get_pkg_dir_from_prefix(register_dir)
490 if not os.path.isfile(register_dir):
491 rospy.logerr(
'widgets register file "%s" not found !'%register_dir)
494 widget_provider = WidgetProvider(register_dir)
497 if child.tag ==
'widget':
499 self._splash.update(child.attrib[
'name'])
501 pkg, xml = widget_provider.get_widget_registered(child.attrib[
'name'])
502 widget = widget_provider.load(pkg, xml)
503 widget.retranslateEvent()
504 self._widgets_list.append(widget)
506 self.footer_ui.central_layout.addWidget(widget.get_widget(),
507 int(child.attrib[
'row']),
508 int(child.attrib[
'column']),
509 int(child.attrib[
'row-span']),
510 int(child.attrib[
'column-span']))
512 widget.get_widget().alarm.connect(self.footer_ui.update_alarm)
516 end_item = self.footer_ui.central_layout.columnCount()
517 spacer = QSpacerItem(20, 20,
518 QSizePolicy.Expanding,
520 self.footer_ui.central_layout.addItem(spacer, 0, end_item)
522 self.central_layout.addWidget(self.
footer_ui, 5, 1)
526 """! Take current plugin, called when user changed or disconnected.
527 @param user: user logged informations.
531 if user.privilege == Privilege.NONE:
533 self.viewer_widget.takeWidget()
535 elif self._current_plugin.get_access_right() > user.privilege:
537 self.viewer_widget.takeWidget()
545 """! Called when emergency stop status changed.
546 @param status: emergency stop status.
549 if status == EmergencyStopState.LOCKED:
550 self.dashboard_widget.setStyleSheet(
"QWidget{background-color: #fed500;}")
551 self.logo_label.setStyleSheet(
"QWidget{background-color: #fed500;}")
553 self.dashboard_widget.setStyleSheet(
"QWidget{background-color: #d9d9d9;}")
554 self.logo_label.setStyleSheet(
"QWidget{background-color: #d9d9d9;}")
557 """! Resize application.
558 @param event: event object.
564 """! This methode call Plugins::shutdown() and Widgets::shutdown().
566 rospy.loginfo(
'Shutdown requested ...')
567 rospy.loginfo(
' - Shutdown Plugins :')
569 for plugin
in self._plugins_list:
571 rospy.loginfo(
" - "+plugin.__class__.__name__+
" -> shutting done.")
573 rospy.loginfo(
' - Shutdown Widgets :')
575 for widget
in self._widgets_list:
577 rospy.loginfo(
" - "+widget.__class__.__name__+
" -> shutting done.")
579 self._emergency_stop.shutdown()
581 rospy.loginfo(
'Shutting done.')
CobotGuiMain class inherit QWidget.
def _parse_config_xml
Parser xml configuration file.
def _setup_launchers
Setup buttons plugins on launcher.
def __init__
The constructor.
def emergency_stop_event
Called when emergency stop status changed.
def _load_plugin_on_viewer
Display plugin on viewer, function called when user select launcher.
def _get_plugin_sender_id
Find and return plugin selected by user.
def _setup_widgets_connections
def _take_current_plugin
Take current plugin, called when user changed or disconnected.
def _setup_dashboard
Setup all widgets on dashbord registered on config file.
def shutdown
This methode call Plugins::shutdown() and Widgets::shutdown().
def _setup_plugins_connections
def _setup_footer
Setup footer.
def resizeEvent
Resize application.