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