00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 import sys
00020
00021 import rospy
00022 import os
00023
00024 from python_qt_binding.QtGui import *
00025 from python_qt_binding.QtCore import *
00026 from python_qt_binding import loadUi
00027 from roslib.packages import get_pkg_dir
00028 from xml.etree import ElementTree
00029
00030 from packages import get_pkg_dir_from_prefix, \
00031 get_ros_workspace_dir, \
00032 get_ros_workspace_src_dir
00033
00034 class _Image:
00035
00036 def __init__(self, node, rsc_path):
00037
00038 self.label = ""
00039 self.src = ""
00040 self.width = 0
00041 self.height = 0
00042 self.scale = True
00043 self.preload = False
00044 self.pixmap = None
00045
00046 try:
00047 self._read_img_node(node)
00048 except Exception as ex:
00049 raise Exception(ex)
00050
00051 self.src = os.path.join(rsc_path, self.src)
00052
00053 if self.preload:
00054 self.pixmap = _Image.loadPixmap(self)
00055
00056
00057 def _read_img_node(self, node):
00058
00059 if len(node.attrib.keys()) != 6:
00060 raise Exception('<img .../> takes exactly 6 arguments (%i given) !'%len(node.attrib.keys()))
00061
00062 for k, v in node.attrib.items():
00063
00064 if k == 'label':
00065 self.label = v
00066 elif k == 'src':
00067 self.src = v
00068 elif k == 'width':
00069 self.width = int(v)
00070 elif k == 'height':
00071 self.height = int(v)
00072 elif k == 'auto-scale':
00073 if v.lower() == 'false':
00074 self.scale = False
00075 else:
00076 self.scale = True
00077 elif k == 'preload':
00078 if v.lower() == 'true':
00079 self.preload = True
00080 else:
00081 self.preload = False
00082 else:
00083 raise Exception('Inconstante parameter type <img %s="..."/>!'%k)
00084
00085 def isPreloaded(self):
00086 return self.preload
00087
00088 @staticmethod
00089 def loadPixmap(img_desc):
00090
00091 try:
00092 px = QPixmap(img_desc.src)
00093
00094 if img_desc.scale is True :
00095 px = px.scaled(img_desc.width, img_desc.height,
00096 Qt.KeepAspectRatio,
00097 Qt.SmoothTransformation)
00098 return px
00099 except Exception as ex:
00100 raise Exception(ex)
00101
00102 def getPixmap(self, w = None, h = None):
00103
00104 rescale = False
00105 if w is not None and h is not None:
00106 if w != self.width or h != self.height:
00107 self.width = w
00108 self.height = h
00109 rescale = True
00110
00111 if self.isPreloaded():
00112 if rescale:
00113 self.pixmap = _Image.loadPixmap(self)
00114 return self.pixmap
00115 else:
00116 return _Image.loadPixmap(self)
00117
00118 class QAgiImageRessource:
00119
00120 def __init__(self, xnode):
00121
00122 if xnode is None or 'path' not in xnode.attrib.keys():
00123 return
00124
00125 self._img_rsc = {}
00126 ipath = get_pkg_dir_from_prefix(xnode.attrib['path'])
00127
00128 if not os.path.isdir(ipath):
00129 raise Exception("Invalid path from images ressource !")
00130
00131 for img_node in xnode:
00132 img = _Image(img_node, ipath)
00133 self._img_rsc.update({img.label : img})
00134
00135 def getPixmap(self, key, w=None, h=None):
00136
00137 try:
00138 img = self._img_rsc[key]
00139 return img.getPixmap(w,h)
00140 except Exception as ex:
00141 raise Exception(str(ex))
00142
00143
00144
00145
00146 def getPixmapSize(self, key):
00147 try:
00148 px = self._img_rsc[key]
00149 return QSize(px.width, px.height)
00150 except Exception as ex:
00151 raise Exception(str(ex))
00152
00153 def getIcon(self, key):
00154 try:
00155 ico = self._img_rsc[key]
00156 return QIcon(ico.src)
00157 except Exception as ex:
00158 raise Exception(str(ex))
00159
00160 def getIconSize(self, key):
00161 try:
00162 ico = self._img_rsc[key]
00163 return QSize(ico.width, ico.height)
00164 except Exception as ex:
00165 raise Exception(str(ex))
00166
00167 class QAgiUiRessource:
00168 def __init__(self, xnode):
00169
00170 if xnode is None or 'path' not in xnode.attrib.keys():
00171 return
00172
00173 self._uis_rsc = {}
00174 gpath = get_pkg_dir_from_prefix(xnode.attrib['path'])
00175
00176 if not os.path.isdir(gpath):
00177 raise Exception("Invalid path from ui ressource !")
00178
00179 for ui in xnode:
00180 uipath = '%s/%s'%(gpath, ui.attrib['src'])
00181 self._uis_rsc.update({ui.attrib['label']: uipath})
00182
00183 def __getitem__(self, key):
00184 try:
00185 return self._uis_rsc[key]
00186 except Exception as ex:
00187 raise Exception(ex)
00188
00189 def load(self, key, widget):
00190 try:
00191 loadUi(self.__getitem__(key), widget)
00192 except Exception as ex:
00193 raise ex
00194
00195 class QAgiYamlRessource:
00196 def __init__(self, xnode):
00197
00198 if xnode is None or 'path' not in xnode.attrib.keys():
00199 return
00200
00201 self._yamls_rsc = {}
00202 gpath = get_pkg_dir_from_prefix(xnode.attrib['path'])
00203
00204 if not os.path.isdir(gpath):
00205 raise Exception("Invalid path from yamls ressource !")
00206
00207 for yaml in xnode:
00208 yamlpath = '%s/%s'%(gpath, yaml.attrib['src'])
00209 self._yamls_rsc.update({yaml.attrib['label']: yamlpath})
00210
00211 def __getitem__(self, key):
00212 try:
00213 return self._yamls_rsc[key]
00214 except Exception as ex:
00215 raise Exception(ex)
00216
00217 class QAgiStyleSheetRessource:
00218
00219 def __init__(self, xnode):
00220
00221 self._node = xnode
00222 self._theme = "default"
00223
00224 if "theme" in self._node.attrib.keys():
00225 self._theme = self._node.attrib["theme"]
00226
00227 def __getitem__(self, key):
00228
00229 xpath = ""
00230 stylesheet = ""
00231
00232 if '.' in key:
00233 keys = key.split('.')
00234 xpath = './sheet[@name="%s"]'%keys[0]
00235 for i in range(1, len(keys)):
00236 xpath+='/sheet[@name="%s"]'%keys[i]
00237 else:
00238 xpath = './sheet[@name="%s"]'%key
00239
00240 xpath += '/%s'%self._theme
00241
00242
00243
00244 try:
00245 sheet = self._node.find(xpath)
00246 stylesheet = sheet.text
00247 except:
00248 rospy.logerr('Style sheet "%s" was not found !'%key)
00249
00250 return stylesheet
00251
00252 class QAgiTraductionRessource:
00253
00254 def __init__(self, xnode):
00255
00256 self._node = xnode
00257 self._lng = "en"
00258
00259 if "lng" in self._node.attrib.keys():
00260 self._lng = self._node.attrib["lng"]
00261
00262 def __getitem__(self, key):
00263
00264 trad = str(key)
00265 xpath = './translate[@src="%s"]/%s'%(str(key), self._lng)
00266
00267 try:
00268 trad = self._node.find(xpath).text
00269 except:
00270 rospy.logerr('Traduction from "%s" not found !'%key)
00271
00272 return trad
00273
00274 class QAgiResources:
00275
00276 DEFAULT_RSC_NAMES = ["rsc","resource","resources"]
00277
00278 def __init__(self, package, dir):
00279
00280 tree = None
00281 root = None
00282 rsc = None
00283
00284 if dir is None:
00285 rsc = self.find_default_rsc_file(package)
00286 if rsc is None:
00287 raise Exception("Connot find ressources file in pakage '%s'"%package)
00288 else:
00289 rsc = os.path.join(get_pkg_dir(package), dir)
00290
00291 try:
00292 tree = ElementTree.parse(rsc)
00293 root = tree.getroot()
00294 except Exception as e:
00295 raise Exception(e)
00296
00297 for node in root:
00298 if node.tag == "uis":
00299 setattr(self, node.tag, QAgiUiRessource(node))
00300 elif node.tag == "images":
00301 setattr(self, node.tag, QAgiImageRessource(node))
00302 elif node.tag == "yamls":
00303 setattr(self, node.tag, QAgiYamlRessource(node))
00304 elif node.tag == "traductions":
00305 setattr(self, node.tag, QAgiTraductionRessource(node))
00306 elif node.tag == "styles":
00307 setattr(self, node.tag, QAgiStyleSheetRessource(node))
00308
00309
00310 def find_default_rsc_file(self, pkg):
00311
00312 pkg_path = get_pkg_dir(pkg)
00313
00314 for name in self.DEFAULT_RSC_NAMES:
00315 dir = os.path.join(pkg_path, name)
00316 if os.path.isdir(dir):
00317 return os.path.join(dir,self.find_rsc_xml(dir))
00318 return None
00319
00320 def find_rsc_xml(self, rsc_dir):
00321
00322 for file in os.listdir(rsc_dir):
00323 file_split = file.split(".")
00324 if file_split[0] in self.DEFAULT_RSC_NAMES and file_split[-1] == "xml":
00325 return file
00326 return None
00327
00328 def loadRsc(package, dir=None):
00329 return QAgiResources(package, dir)
00330
00331 import copy
00332
00333 def loadRes(package):
00334
00335 from packages import QAgiPackages
00336
00337 res_class_name = ''
00338
00339 for subs in package.split('_'):
00340 res_class_name+=subs[0].upper()+subs[1:]
00341 res_class_name+="Res"
00342
00343 print 'Loading ressource name : %s'%res_class_name
00344
00345 return QAgiPackages.__pkg__(package).__module__('resources.res').__import__(res_class_name)
00346