plugin_provider.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 ################################################################################
3 #
4 # Copyright Airbus Group SAS 2015
5 # All rigths reserved.
6 #
7 # File Name : plugin_provider.py
8 # Authors : Martin Matignon
9 #
10 # If you find any bug or if you have any question please contact
11 # Adolfo Suarez Roos <adolfo.suarez@airbus.com>
12 # Martin Matignon <martin.matignon.external@airbus.com>
13 #
14 #
15 ################################################################################
16 
17 import rospy
18 import uuid
19 import os
20 import sys
21 
22 import __builtin__
23 import traceback
24 from xml.etree import ElementTree
25 from roslib.packages import get_pkg_dir
26 
27 from airbus_cobot_gui import airbus_cobot_gui_dir
28 from airbus_cobot_gui.exception.exception import CobotGuiException
29 
30 from airbus_pyqt_extend.QtAgiCore import get_pkg_dir_from_prefix
31 
32 ## @package: plugin_provider
33 ## @version 4.0
34 ## @author Matignon Martin
35 ## @date Last modified 28/02/2014
36 ## @class PluginProvider
37 ## @brief Class for load Python plugin package.
39 
40  """
41  PluginProvider interacts with ros plugin package. The first is its
42  import plugin, and the second is the set plugin configuration which
43  it reads.
44  """
45 
46  def __init__(self, xml_register_dir):
47  """! The constructor."""
48 
49  self._label = ""
50 
51  #Check dir
52  if not os.path.isfile(xml_register_dir):
53  raise CobotGuiException('Plugins register file "%s" in package "airbus_cobot_gui" not found'
54  %(xml_register_dir))
55 
56  #Parse xml file
57  try:
58  self._plugin_register = ElementTree.parse(xml_register_dir)
59  except Exception as e:
60  raise CobotGuiException(str(e))
61 
62  def get_plugin_registered(self, plugin_label):
63  """! Find plugin package name and xml name registered in plugins_register.xml.
64  @param plugin_label: plugin label.
65  @type package_name: string.
66 
67  @return plugin_desc: package name and xml file name.
68  @type plugin_desc: tuple (string, string).
69  """
70 
71  self._label = plugin_label
72 
73  root = self._plugin_register.getroot()
74 
75  #Find and read node label
76  plugin_desc = root.find('./plugin[@label="%s"]'%plugin_label)
77 
78  if plugin_desc is None:
79  return None, None
80  else:
81  return plugin_desc.attrib['package'], plugin_desc.attrib['plugin-xml']
82 
83  def load(self, node, plugin_label):
84  """! Load Python package.
85  @param package_name: package name.
86  @type package_name: string.
87 
88  @param plugin_xml: xml file name.
89  @type plugin_xml: string.
90 
91  @return plugin_instance: plugin instance.
92  @type plugin_instance: CobotUiPlugin.
93  """
94 
95  package_name, plugin_xml = self.get_plugin_registered(plugin_label)
96 
97  package, config, parameters = self._parse_plugin_xml(package_name, plugin_xml)
98 
99  sys.path.append(package['package_path'])
100 
101  #Import package module
102  #Raise exception
103  try:
104  module = __builtin__.__import__(package['module_name'],
105  fromlist=[package['class_name']],
106  level=0)
107  except NotImplementedError as e:
108  rospy.logerr('PluginProvider::load(%s,%s): raised an exception:\n%s'
109  %(package_name, plugin_xml, e))
110  return None
111  except Exception as e:
112  raise CobotGuiException('PluginProvider::load exception raised in import_module(%s, %s):\n%s'
113  %(package['module_name'], package['class_name'],traceback.format_exc()))
114 
115  #Get referance to plugin class
116  plugin_ref = getattr(module, package['class_name'], None)
117 
118  if plugin_ref is None:
119  rospy.logerr('PluginProvider::load could not find plugin %s.%s !'
120  %(package['module_name'], package['class_name'], module))
121  return None
122 
123  for param in node:
124  if param.tag == "param":
125  try:
126  parameters[param.attrib["name"]] = param.attrib["value"]
127  except:
128  parameters.update({param.attrib["name"] : param.attrib["value"]})
129 
130  try:
131  plugin_instance = plugin_ref()
132  plugin_instance.set_params(parameters)
133  plugin_instance.setup()
134  plugin_instance.install(config)
135  plugin_instance.exit()
136  except Exception as e:
137  raise CobotGuiException('PluginProvider.plugin_instance raised with exception %s'%e)
138 
139  return plugin_instance
140 
141  def _parse_plugin_xml(self, package_name, plugin_xml):
142  """! Read plugin xml file.
143  @param package_name: python pakage name.
144  @type package_name: string.
145 
146  @param plugin_xml: plugin xml name.
147  @type plugin_xml: string.
148 
149  @return: plugin_desc: package descrition, plugin configuration.
150  @type plugin_desc: tuple (dictonary, dictonary).
151  """
152 
153  package = {'package_path' : None,
154  'module_name' : None,
155  'class_name' : None}
156 
157  config = {'label' : self._label, 'description' : None,
158  'icon' : None, 'style-sheet' : None, 'restriction': None}
159 
160  pkg_dir = get_pkg_dir(package_name)
161 
162  path = '/'.join([pkg_dir, plugin_xml])
163 
164  if not os.path.isfile(path):
165  rospy.logerr('PluginProvider._parse_plugin_xml() plugin file "%s" in package "%s" not found'
166  %(plugin_xml, package_name))
167  return None
168 
169  try:
170  tree = ElementTree.parse(path)
171  except Exception:
172  return None
173 
174  path = [pkg_dir,tree.getroot().attrib['path']]
175 
176  package['package_path'] = '/'.join(path)
177 
178  plugin_import = tree.getroot().find('./class').attrib['import']
179 
180  config['description'] = tree.getroot().find('./description').text
181 
182  # separate module name and class name
183  module_name, class_name = plugin_import.rsplit('.', 1)
184  package['module_name'] = module_name
185  package['class_name'] = class_name
186 
187  config_node = tree.getroot().find('./init')
188 
189  for child in config_node:
190  if child.tag == 'icon':
191  config['icon'] = get_pkg_dir_from_prefix(child.text, pkg_dir)
192  elif child.tag == 'style-sheet':
193  if child.text != None and child.text != 'none':
194  config['style-sheet'] = child.text
195  elif child.tag == 'access-rights':
196  config['restriction'] = child.text
197  else:
198  pass
199 
200  parameters_node = tree.getroot().find('./parameters')
201  parameters = {}
202 
203  param_type={"string": str,
204  "int" : int,
205  "float" : float}
206 
207  if parameters_node is not None:
208 # parameters = {}
209  for param in parameters_node:
210  name = param.attrib['name']
211  type = param_type[param.attrib['type']]
212  value = param.attrib['value']
213  parameters.update({name : type(value)})
214 
215  return package, config, parameters
216 
217 from python_qt_binding.QtGui import *
218 from python_qt_binding.QtCore import *
220 
222 
223  def __init__(self, parent):
224  QPopup.__init__(self, parent)
225 
226  self.setAttribute(Qt.WA_TranslucentBackground)
227  self.setStyleSheet("background:transparent;")
228  self.setLinks(QPopup.TopRight, QPopup.TopLeft)
229 
230  self._launchers_layout = QVBoxLayout(self)
231  self._launchers_layout.setContentsMargins(20, 2, 2, 2)
232  self._launchers_layout.setSpacing(15)
233  self._launchers_layout.setSizeConstraint(QLayout.SetMaximumSize)
234 
235  def setup_launchers(self, launchers):
236 
237  for launcher in launchers:
238  self.connect(launcher, SIGNAL('clicked()'), self.close)
239  self._launchers_layout.addWidget(launcher)
240 
241 class PluginsGroup(QPushButton):
242 
243  def __init__(self, parent, group_name, icon):
244  QPushButton.__init__(self, parent)
245  self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
246 
247  self._launchers = []
248 
249  icon_path = get_pkg_dir_from_prefix(icon)
250 
251  if os.access(icon_path, os.W_OK):
252  self.setIcon(QIcon(icon_path))
253  else:
254  self.setStyleSheet("background-color:rgba(255,0,0,80%);\
255  border-radius: 10px;\
256  font-size: 12pt;\
257  font-weight:60;\
258  color: #ffffff;")
259  self.setText(group_name)
260 
261  def resizeLaunchers(self, size):
262 
263  for launcher in self._launchers:
264  launcher.setFixedSize(size)
265  launcher.setIconSize(size)
266 
267  def add(self, launcher):
268  launcher.setStyleSheet("background:none;")
269  self._launchers.append(launcher)
270 
271  def mousePressEvent(self, event):
272 
273  popup = PluginsGroupPopup(self)
274  popup.setup_launchers(self._launchers)
275 
276  popup.show_()
277 
278 #End of file
279 
def get_plugin_registered
Find plugin package name and xml name registered in plugins_register.xml.
Class for load Python plugin package.


airbus_cobot_gui
Author(s):
autogenerated on Thu Dec 17 2015 11:42:05