ScolaSync  4.0
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
ownedUsbDisk.py
Aller à la documentation de ce fichier.
1 # -*- coding: utf-8 -*-
2 # $Id: ownedUsbDisk.py 47 2011-06-13 10:20:14Z georgesk $
3 
4 licence={}
5 licence['en']="""
6  file ownedUsbDisk.py
7  this file is part of the project scolasync
8 
9  Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
10 
11  This program is free software: you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version3 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program. If not, see <http://www.gnu.org/licenses/>.
23 """
24 
25 python3safe=True
26 import usbDisk, db
27 import os.path, dbus, subprocess, time
28 from PyQt4.QtCore import *
29 from PyQt4.QtGui import *
30 from globaldef import markFileName
31 
32 """
33 liste statique pour éviter de demander chaque seconde le nom d'un
34 propriétaire de clé si on n'a pas souhaité le donner.
35 """
36 
37 ##
38 #
39 # Renvoie le tatouage pour un point de montage donné, quitte à le créer
40 # si nécessaire.
41 # @param mountPoint un point de montage de partition
42 # @return le tatouage
43 #
44 def tattooInDir(mountPoint):
45  tattooFileName = os.path.join(mountPoint,".scolasync-tattoo")
46  tattoo_=""
47  if os.path.exists(tattooFileName):
48  tattoo_=open(tattooFileName,"r").readlines()[0].strip()
49  if tattoo_ != "" :
50  # le tatouage existe déjà, on renvoie sa valeur
51  return tattoo_
52  else:
53  tattoo_="%12.2f" %time.time()
54  time.sleep(0.05)
55  # si on espace deux créations de tatouages de 50 millisecondes
56  # il est impossible d'avoir deux tatouages identiques générés
57  # par le même ordinateur. Les chances que ça arrive avec des
58  # ordinateurs distincts sont minimes
59  outfile=open(tattooFileName,"w")
60  outfile.write(tattoo_)
61  outfile.close()
62  # on renvoie le nouveau tatouage
63  return tattoo_
64 
65 ##
66 #
67 # édition de la base de données
68 # @param owd une instance de ownedUsbDisk
69 # @param hint chaîne vide par défaut. Peut être le nom de l'ancien propriétaire
70 #
71 def editRecord(owd, hint=""):
72  title=QApplication.translate("Dialog", "Choix du propriétaire", None, QApplication.UnicodeUTF8)
73  prompt=QApplication.translate("Dialog", "Nouveau nom du propriétaire du baladeur", None, QApplication.UnicodeUTF8)
74  newStudent, ok = QInputDialog.getText(None, title, prompt, text=hint)
75  if ok:
76  newStudent="%s" %newStudent
77  db.writeStudent(owd.stickid, owd.getFatUuid(), owd.tattoo(), newStudent)
78 
79 ##
80 #
81 # une classe qui ajoute un nom de propriétaire aux disque USB,
82 # et qui en même temps ajoute des particularités selon le nom du
83 # vendeur et le modèle.
84 #
86  ##
87  #
88  # @param path un chemin dans le système dbus
89  # @param bus un objet dbus.BusSystem
90  #
91  def __init__(self, path, bus):
92  usbDisk.uDisk.__init__(self,path, bus)
93  QObject.__init__(self)
94  self.owner="" # le propriétaire est déterminé plus tard
95  self.vendor=self.getProp("drive-vendor")
96  self.model=self.getProp("drive-model")
97  self.visibleDirs=self.readQuirks()
98 
99  ##
100  #
101  # @return un identifiant unique, composé du nom du propriétaire
102  # suivi du tatouage
103  #
104  def uniqueId(self):
105  return "%s~%s" %(self.owner, self.tattoo())
106 
107  ##
108  #
109  # Renvoie un tatouage présent sur la clé, quitte à le créer.
110  # @result un tatouage, supposément unique.
111  #
112  def tattoo(self):
113  ff=self.getFirstFat()
114  if ff:
115  fatPath=ff.ensureMounted()
116  return tattooInDir(fatPath)
117  else:
118  return ""
119 
120  ##
121  #
122  # Lit un dictionnaire indexé par le noms de vendeurs et les noms de modèle
123  # pour associer à ces modèles particuliers un répertoire visible.
124  # voir la fonction visibleDir. Ce dictionnaire est dans le fichier
125  # /usr/share/scolasync/marques.py ou dans ${HOME}/.scolasync/marques.py,
126  # (sous Linux) cette dernière place étant prépondérante.
127  #
128  def readQuirks (self):
129  f1="/usr/share/scolasync/marques.py"
130  f2=os.path.expanduser(markFileName)
131  if os.path.exists(f2):
132  f=f2
133  else:
134  f=f1
135  result=eval(open(f,"r", encoding="utf-8").read())
136  return result
137 
138  ##
139  #
140  # Renvoie le répertoire particulier de la partition qui sera visible
141  # quand le baladeur est utilisé par son interface utilisateur. Ce
142  # répertoire peut varier selon les vendeurs et les modèles.
143  #
144  def visibleDir(self):
145  k=self.vendor+":"+self.model
146  if k in self.visibleDirs.keys():
147  return self.visibleDirs[k]
148  else:
149  return "."
150 
151  ##
152  #
153  # Méthode statique
154  # renvoie des titres pour les items obtenus par __getitem__
155  # la deuxième colonne sera toujours le propriétaire
156  # @param locale la locale, pour traduire les titres
157  # @return une liste de titres de colonnes
158  #
159  def headers(locale="C"):
160  result=usbDisk.uDisk.headers(locale)
161  ownerProp=QApplication.translate("uDisk","owner",None, QApplication.UnicodeUTF8)
162  result.insert(1,ownerProp)
163  return result
164 
165  ##
166  #
167  # renvoie un nom de propriétaire dans tous les cas.
168  #
169  def ownerByDb(self):
170  if self.owner != "":
171  return self.owner
172  else:
173  s=db.readStudent(self.stickid, self.getFatUuid(), self.tattoo())
174  if s != None:
175  self.owner=s
176  return s
177  else:
178  return QApplication.translate("Dialog","inconnu",None, QApplication.UnicodeUTF8)
179 
180  ##
181  #
182  # renvoie un élément de listage de données internes au disque
183  # Fait en sorte que la deuxième colonne soit toujours le propriétaire
184  # @param n un nombre
185  # @return si n==-1, renvoie self ; renvoie un élément si n>0, et le drapeau self.selected si n==0. Les noms des éléments sont dans la liste self.itemNames
186  #
187  def __getitem__(self,n):
188  propListe=usbDisk.uDisk.headers()
189  if n == -1:
190  return self # pour accéder à toutes les données d'une partition
191  elif n==0:
192  return self.selected
193  elif n==1:
194  return self.ownerByDb()
195  else:
196  return self.unNumberProp(n)
197 
198 
199  headers = staticmethod(headers)
200 
201  ##
202  #
203  # Demande un nom de propriétaire si celui-ci n'est pas encore défini
204  # pour cette clé USB
205  # @param noLoop si True : ne fait pas de dialogue interactif
206  # @return un nom de propriétaire si c'est un disque, sinon None
207  #
208  def ensureOwner(self, noLoop):
209  if self.getProp("device-is-drive") and self.isUsbDisk():
210  if noLoop==False and not db.knowsId(self.stickid, self.getFatUuid(), self.tattoo()) :
211  prompt=QApplication.translate("Dialog","La cle {id}<br>n'est pas identifiee, donnez le nom du proprietaire",None, QApplication.UnicodeUTF8).format(id=self.stickid)
212  title=QApplication.translate("Dialog","Entrer un nom",None, QApplication.UnicodeUTF8)
213  text,ok = QInputDialog.getText(None, title, prompt)
214  if ok and len(text)>0 and not db.hasStudent(text):
215  db.writeStudent(self.stickid, self.getFatUuid(), self.tattoo(), text)
216  return db.readStudent(self.stickid, self.getFatUuid(), self.tattoo())
217 
218 ##
219 #
220 # Une classe qui fournit une collection de disques USB connectés,
221 # avec leurs propriétaires. Les propriétaires sont recensés juste
222 # avant le montage des partions FAT.
223 #
225 
226  ##
227  #
228  # Le constructeur est un proxy pour usbDisk.Available.__init__
229  # qui force la classe de disques à utiliser : en effet ici
230  # uDisk désigne ownedUsbDisk.uDisk
231  # @param access le mode d'accès : 'disk' ou 'firstFat'
232  # @param diskClass la classe d'objets à créer pour chaque disque
233  # @param diskDict un dictionnaire des disque maintenu par deviceListener
234  # @param noLoop doit être True pour éviter de lancer un dialogue
235  #
236  def __init__(self, access="disk", diskClass=uDisk, diskDict=None, noLoop=True):
237  self.noLoop=noLoop
238  usbDisk.Available.__init__(self, access, diskClass, diskDict)
239 
240  ##
241  #
242  # Fin de l'initialisation : trouve les propriétaires des disques
243  # puis identifie les partitions FAT et les monte
244  #
245  def finishInit(self):
246  self.getFirstFats() # premier passage, pour repérer chaque partition FAT
247  for d in self.disks.keys():
248  d.owner=d.ensureOwner(self.noLoop)
249  self.mountFirstFats()
250 
251 if __name__=="__main__":
252  machin=Available()
253  print (machin)
254 
255