ScolaSync  1.0
ownedUsbDisk.py
Aller à la documentation de ce fichier.
00001 # -*- coding: utf-8 -*-    
00002 #       $Id: ownedUsbDisk.py 47 2011-06-13 10:20:14Z georgesk $ 
00003 
00004 licence={}
00005 licence['en']="""
00006     file ownedUsbDisk.py
00007     this file is part of the project scolasync
00008     
00009     Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
00010 
00011     This program is free software: you can redistribute it and/or modify
00012     it under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version3 of the License, or
00014     (at your option) any later version.
00015 
00016     This program is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU General Public License for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 """
00024 
00025 
00026 import usbDisk, db
00027 import os.path, dbus, subprocess, time
00028 from PyQt4.QtCore import *
00029 from PyQt4.QtGui import *
00030 from globaldef import markFileName
00031 
00032 """
00033 liste statique pour éviter de demander chaque seconde le nom d'un
00034 propriétaire de clé si on n'a pas souhaité le donner.
00035 """
00036 
00037 ##
00038 # 
00039 #     Renvoie le tatouage pour un point de montage donné, quitte à le créer
00040 #     si nécessaire.
00041 #     @param mountPoint un point de montage de partition
00042 #     @return le tatouage
00043 #     
00044 def tattooInDir(mountPoint):
00045     tattooFileName = os.path.join(mountPoint,".scolasync-tattoo")
00046     tattoo_=""
00047     if os.path.exists(tattooFileName):
00048         tattoo_=open(tattooFileName,"r").readlines()[0].strip()
00049     if tattoo_ != "" :
00050         # le tatouage existe déjà, on renvoie sa valeur
00051         return tattoo_
00052     else:
00053         tattoo_="%12.2f" %time.time()
00054         time.sleep(0.05)
00055         # si on espace deux créations de tatouages de 50 millisecondes
00056         # il est impossible d'avoir deux tatouages identiques générés
00057         # par le même ordinateur. Les chances que ça arrive avec des
00058         # ordinateurs distincts sont minimes
00059         outfile=open(tattooFileName,"w")
00060         outfile.write(tattoo_)
00061         outfile.close()
00062         # on renvoie le nouveau tatouage
00063         return tattoo_
00064 
00065 ##
00066 # 
00067 #     édition de la base de données
00068 #     @param owd une instance de ownedUsbDisk
00069 #     @param hint chaîne vide par défaut. Peut être le nom de l'ancien propriétaire
00070 #     
00071 def editRecord(owd, hint=""):
00072     title=QApplication.translate("Dialog", "Choix du propriétaire", None, QApplication.UnicodeUTF8)
00073     prompt=QApplication.translate("Dialog", "Nouveau nom du propriétaire du baladeur", None, QApplication.UnicodeUTF8)
00074     newStudent, ok = QInputDialog.getText(None, title, prompt, text=hint)
00075     if ok:
00076         newStudent=u"%s" %newStudent
00077         db.writeStudent(owd.stickid, owd.getFatUuid(), owd.tattoo(), newStudent)
00078 
00079 ##
00080 # 
00081 #     une classe qui ajoute un nom de propriétaire aux disque USB,
00082 #     et qui en même temps ajoute des particularités selon le nom du
00083 #     vendeur et le modèle.
00084 #     
00085 class uDisk(usbDisk.uDisk,QObject):
00086     ##
00087     # 
00088     #         @param path un chemin dans le système dbus
00089     #         @param bus un objet dbus.BusSystem
00090     #         @param checkable vrai si on fera usage de self.selected
00091     #         
00092     def __init__(self, path, bus, checkable=False):
00093         usbDisk.uDisk.__init__(self,path, bus, checkable)
00094         QObject.__init__(self)
00095         self.owner="" # le propriétaire est déterminé plus tard
00096         self.vendor=self.getProp("drive-vendor")
00097         self.model=self.getProp("drive-model")
00098         self.visibleDirs=self.readQuirks()
00099 
00100     ##
00101     # 
00102     #         @return un identifiant unique, composé du nom du propriétaire
00103     #         suivi du tatouage
00104     #         
00105     def uniqueId(self):
00106         return "%s~%s" %(self.owner, self.tattoo())
00107 
00108     ##
00109     # 
00110     #         Renvoie un tatouage présent sur la clé, quitte à le créer.
00111     #         @result un tatouage, supposément unique.
00112     #         
00113     def tattoo(self):
00114         ff=self.getFirstFat()
00115         if ff:
00116             fatPath=ff.ensureMounted()
00117             return tattooInDir(fatPath)
00118         else:
00119             return ""
00120     
00121     ##
00122     # 
00123     #         Lit un dictionnaire indexé par le noms de vendeurs et les noms de modèle
00124     #         pour associer à ces modèles particuliers un répertoire visible.
00125     #         voir la fonction visibleDir. Ce dictionnaire est dans le fichier
00126     #         /usr/share/scolasync/marques.py ou dans ${HOME}/.scolasync/marques.py,
00127     #         (sous Linux) cette dernière place étant prépondérante.
00128     #         
00129     def readQuirks (self):
00130         f1="/usr/share/scolasync/marques.py"
00131         f2=os.path.expanduser(markFileName)
00132         if os.path.exists(f2):
00133             f=f2
00134         else:
00135             f=f1
00136         result=eval(open(f,"r").read())
00137         return result
00138         
00139     ##
00140     # 
00141     #         Renvoie le répertoire particulier de la partition qui sera visible
00142     #         quand le baladeur est utilisé par son interface utilisateur. Ce
00143     #         répertoire peut varier selon les vendeurs et les modèles.
00144     #         
00145     def visibleDir(self):
00146         k=self.vendor+":"+self.model
00147         if k in self.visibleDirs.keys():
00148             return self.visibleDirs[k]
00149         else:
00150             return "."
00151 
00152     ##
00153     # 
00154     #         Méthode statique
00155     #         renvoie des titres pour les items obtenus par __getitem__
00156     #         la deuxième colonne sera toujours le propriétaire
00157     #         @param checkable vrai si le premier en-tête correspond à une colonne de cases à cocher
00158     #         @param locale la locale, pour traduire les titres
00159     #         @return une liste de titres de colonnes
00160     #         
00161     def headers(checkable=False,locale="C"):
00162         result=usbDisk.uDisk.headers(checkable, locale)
00163         ownerProp=QApplication.translate("uDisk","owner",None, QApplication.UnicodeUTF8)
00164         result.insert(1,ownerProp)
00165         return result
00166 
00167     ##
00168     # 
00169     #         renvoie un nom de propriétaire dans tous les cas.
00170     #         
00171     def ownerByDb(self):
00172         if self.owner != "":
00173             return self.owner
00174         else:
00175             s=db.readStudent(self.stickid, self.getFatUuid(), self.tattoo())
00176             if s != None:
00177                 self.owner=s
00178                 return s
00179             else:
00180                 return QApplication.translate("Dialog","inconnu",None, QApplication.UnicodeUTF8)
00181 
00182     ##
00183     # 
00184     #         renvoie un élément de listage de données internes au disque
00185     #         Fait en sorte que la deuxième colonne soit toujours le propriétaire
00186     #         @param n un nombre
00187     #         @param checkable vrai si on doit renvoyer une propriété supplémentaire pour n==0
00188     #         @return si n==-1, renvoie self ; si checkable est vrai, renvoie un élément si n>0, et le drapeau self.selected si n==0 ; sinon un élément de façon ordinaire. Les noms des éléments sont dans la liste self.itemNames
00189     #         
00190     def __getitem__(self,n):
00191         propListe=usbDisk.uDisk.headers()
00192         if n == -1:
00193             return self # pour accéder à toutes les données d'une partition
00194         if self.checkable:
00195             if n==0:
00196                 return self.selected
00197             elif n==1:
00198                 return self.ownerByDb()
00199             elif n==2:
00200                 return self.unNumberProp(0)
00201             else:
00202                 return self.unNumberProp(n-1)
00203         else:
00204             if n==0:
00205                 return self.unNumberProp(0)
00206             elif n==1:
00207                 return self.ownerByDb()
00208             else:
00209                 return self.unNumberProp(n)
00210     
00211     
00212     headers = staticmethod(headers)
00213 
00214     ##
00215     # 
00216     #         Demande un nom de propriétaire si celui-ci n'est pas encore défini
00217     #         pour cette clé USB
00218     #         @param noLoop si True : ne fait pas de dialogue interactif
00219     #         @return un nom de propriétaire si c'est un disque, sinon None
00220     #         
00221     def ensureOwner(self, noLoop):
00222         if self.getProp("device-is-drive") and self.isUsbDisk():
00223             if noLoop==False and not db.knowsId(self.stickid, self.getFatUuid(), self.tattoo()) :
00224                 prompt=QApplication.translate("Dialog","La cle %1<br>n'est pas identifiee, donnez le nom du proprietaire",None, QApplication.UnicodeUTF8).arg(self.stickid)
00225                 title=QApplication.translate("Dialog","Entrer un nom",None, QApplication.UnicodeUTF8)
00226                 text,ok = QInputDialog.getText(None, title, prompt)
00227                 text = u"%s" %text.toUtf8()
00228                 if ok and len(text)>0 and not db.hasStudent(text):
00229                     db.writeStudent(self.stickid, self.getFatUuid(), self.tattoo(), text)
00230         return db.readStudent(self.stickid, self.getFatUuid(), self.tattoo())
00231         
00232 ##
00233 # 
00234 #     Une classe qui fournit une collection de disques USB connectés,
00235 #     avec leurs propriétaires. Les propriétaires sont recensés juste
00236 #     avant le montage des partions FAT.
00237 #     
00238 class Available(usbDisk.Available):
00239 
00240     ##
00241     # 
00242     #         Le constructeur est un proxy pour usbDisk.Available.__init__
00243     #         qui force la classe de disques à utiliser : en effet ici
00244     #         uDisk désigne ownedUsbDisk.uDisk
00245     #         @param checkable True si on veut pouvoir sélectionner des disques en cochant
00246     #         @param access le mode d'accès : 'disk' ou 'firstFat'
00247     #         @param diskClass la classe d'objets à créer pour chaque disque
00248     #         @param diskDict un dictionnaire des disque maintenu par deviceListener
00249     #         @param noLoop doit être True pour éviter de lancer un dialogue
00250     #         
00251     def __init__(self, checkable=False, access="disk", diskClass=uDisk, diskDict=None, noLoop=True):
00252         self.noLoop=noLoop
00253         usbDisk.Available.__init__(self, checkable, access, diskClass, diskDict)
00254         
00255     ##
00256     # 
00257     #         Fin de l'initialisation : trouve les propriétaires des disques
00258     #         puis identifie les partitions FAT et les monte
00259     #         
00260     def finishInit(self):
00261         self.getFirstFats() # premier passage, pour repérer chaque partition FAT
00262         for d in self.disks.keys():
00263             d.owner=d.ensureOwner(self.noLoop)
00264         self.mountFirstFats()
00265 
00266 
 Tout Classes Espaces de nommage Fichiers Fonctions Variables