1 # Statistiques SVG avec Python
    2 #
    3 # auteur : Frédéric Laurent
    4 # http://www.opikanoba.org
    5 
    6 import os
    7 import os.path
    8 import string
    9 import webbrowser
   10 import tempfile
   11 import SVGdraw
   12 
   13 XMAX=100
   14 STEP=20
   15 YMAX=100
   16 BAR_THICKNESS= 20
   17 SPACE= 10
   18 
   19 class DirectoryExplorer:
   20     def __init__(self):
   21         self.svgURL=tempfile.gettempdir()+"result.svg"
   22         self.infos = []
   23         self.totalSize = 0
   24         self.rootSize=0
   25         self.rootName=None
   26 
   27     def tupleCmp(self, a,b):
   28         (nameA, sizeA) = a
   29         (nameB, sizeB) = b
   30         return cmp(sizeB,sizeA)
   31 
   32     def gatherSize(self, directory, level, deep=1):
   33         listdir = os.listdir(directory)
   34         filelist = filter(lambda f:os.path.isfile(os.path.join(directory, f)), listdir)
   35         weight = sum([os.path.getsize(os.path.join(directory, name)) for name in filelist])
   36         subdir = filter(lambda f: os.path.isdir(os.path.join(directory, f)), listdir)
   37         subdir_w = sum([self.gatherSize(os.path.join(directory,f),level,deep+1) for f in subdir])
   38         total = weight+subdir_w
   39         if (deep<=level):
   40             if (deep==1):
   41                 self.totalSize = total
   42                 self.rootSize = weight
   43                 self.rootName=directory
   44                 self.infos.append((directory,self.rootSize))
   45             else:
   46                 self.infos.append((directory,total))
   47         return total
   48 
   49     def toSVG(self):
   50         #modification du maximum en X : depend du nombre d'element
   51         global XMAX
   52         XMAX = len(self.infos)*(BAR_THICKNESS+SPACE)
   53         # creation du document
   54         doc=SVGdraw.drawing()
   55         svg=SVGdraw.svg(None, '100%','100%')
   56 
   57         # creation des patterns pour les axes et la grille
   58         axeX = SVGdraw.pattern(id="axeX",width="20",height="10",patternUnits="userSpaceOnUse")
   59         axeX.addElement(SVGdraw.path("M 0 0, L 0 10","none","black","0.25"))
   60         axeX.addElement(SVGdraw.path("M 10 10, V 5","none","lightgray","0.25"))
   61         axeY = SVGdraw.pattern(id="axeY",width="10",height="20",patternUnits="userSpaceOnUse")
   62         axeY.addElement(SVGdraw.path("M 0 0, L 10 0","none","black","0.25"))
   63         axeY.addElement(SVGdraw.path("M 5 10, L 10 10","none","lightgray","0.25"))
   64         grid = SVGdraw.pattern(id="grid",width="10",height="10",patternUnits="userSpaceOnUse")
   65         grid.addElement(SVGdraw.path("M 0 0, L 10 0, L 10 10,L 0 10, L 0 0","none","lightgray","0.25"))
   66 
   67         defs=SVGdraw.defs()
   68         defs.addElement(axeX)
   69         defs.addElement(axeY)
   70         defs.addElement(grid)
   71         svg.addElement(defs)
   72 
   73         group=SVGdraw.group(transform="translate(130,130) scale(1,-1)")
   74 
   75         # dessin de la grille de fond
   76         group.addElement(SVGdraw.rect(0,0,XMAX,YMAX,"url(#grid)","lightgray","0.25"))
   77 
   78         # dessin des axes
   79         group.addElement(SVGdraw.rect(0,-10,XMAX,10,"url(#axeX)"))
   80         group.addElement(SVGdraw.rect(-10,0,10,YMAX,"url(#axeY)"))
   81         group.addElement(SVGdraw.line(0,0,XMAX,0,"black",1))
   82         group.addElement(SVGdraw.line(0,0,0,YMAX,"black",1))
   83         # dessin des fleches des axes
   84         group.addElement(SVGdraw.polygon([[-3,YMAX],[3,YMAX],[0,YMAX+10]], "black","white"))
   85         group.addElement(SVGdraw.polygon([[XMAX,-3],[XMAX,3],[XMAX+10,0]], "black","white"))
   86 
   87         textgroup=SVGdraw.group(transform="scale(1,-1)")
   88         # graduations
   89         for y in range(0,YMAX+STEP,STEP):
   90             textgroup.addElement(SVGdraw.text(-STEP,y, str(y), 8, text_anchor="middle", transform="translate(0,%d)"%(-y*2)))
   91         textgroup.addElement(SVGdraw.text(0,YMAX+SPACE, r"%", 8, transform="translate(0,%d)"%(-(YMAX+SPACE)*2)))
   92 
   93         # ajout de la legende principale
   94         legendText = "Repertoire %s - taille %.02f ko"%(self.rootName,float(self.totalSize/1024.0))
   95         textgroup.addElement(SVGdraw.text(XMAX,YMAX+3*SPACE, legendText,12, "verdana",
   96             text_anchor="end", fill="darkblue",transform="translate(0,%d)"%(-(YMAX+3*SPACE)*2)))
   97 
   98         group.addElement(textgroup)
   99 
  100         # tri des elements selon la taille occupee
  101         self.infos.sort(self.tupleCmp)
  102 
  103         xincr=0
  104         #self.infos
  105         for (name,size) in self.infos:
  106             # calcul du pourcentage de place occupe
  107             pourcent = (100.0*float(size))/float(self.totalSize)
  108             height=int(pourcent*YMAX/100);
  109             # insertion du texte de l'emplacement sur le disque et de la taille occupee en Ko
  110             legendText = "%s (%### ###.02f ko)"%(name,float(size/1024.0))
  111             legend = SVGdraw.text(xincr+BAR_THICKNESS/2, -10,legendText,8,"verdana",text_anchor="begin",fill="blue")
  112             legend.attributes["transform"]="scale(1,-1) translate(0,20) rotate(45,%d,-10)"%(xincr+BAR_THICKNESS/2)
  113             group.addElement(legend)
  114 
  115             #insertion de la barre representant le pourcentage
  116             group.addElement(SVGdraw.rect(xincr,0,BAR_THICKNESS, height,"green","black",opacity=0.5))
  117 
  118             #insertion de la taille en pourcentage a gauche de la barre
  119             pourcentText=SVGdraw.text(xincr+BAR_THICKNESS/2, height+SPACE,"%02.01f%% "%pourcent,6,
  120                 "arial", text_anchor="middle", fill="black")
  121             pourcentText.attributes["transform"]="scale(1,-1) translate(0,-%d)"%((height+SPACE)*2)
  122             group.addElement(pourcentText)
  123             # augmentation du l'abscisse en X
  124             xincr = xincr+BAR_THICKNESS+SPACE
  125 
  126         svg.addElement(group)
  127         doc.setSVG(svg)
  128         doc.toXml(self.svgURL)
  129 
  130 if __name__=="__main__":
  131     de = DirectoryExplorer()
  132     de.gatherSize(r"c:\Python",2)
  133     de.toSVG()
  134     webbrowser.open(de.svgURL)