ScolaSync  5.1
ownedUsbDisk.py
Aller à la documentation de ce fichier.
1 # $Id: ownedUsbDisk.py 47 2011-06-13 10:20:14Z georgesk $
2 
3 licence={}
4 licence['en']="""
5  file ownedUsbDisk.py
6  this file is part of the project scolasync
7 
8  Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version3 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 """
23 
24 import usbDisk2, db
25 import os.path, dbus, subprocess, time, random
26 from PyQt5.QtCore import *
27 from PyQt5.QtWidgets import *
28 from globaldef import markFileName
29 
30 """
31 liste statique pour éviter de demander chaque seconde le nom d'un
32 propriétaire de clé si on n'a pas souhaité le donner.
33 """
34 
35 # Renvoie le tatouage pour un point de montage donné, quitte à le créer
36 # si nécessaire.
37 # @param mountPoint un point de montage de partition
38 # @return le tatouage
39 #
40 
41 def tattooInDir(mountPoint):
42  tattooFileName = os.path.join(mountPoint,".scolasync-tattoo")
43  tattoo_=""
44  if os.path.exists(tattooFileName):
45  tattoo_=open(tattooFileName,"r").readlines()[0].strip()
46  if tattoo_ != "" :
47  # le tatouage existe déjà, on renvoie sa valeur
48  return tattoo_
49  else:
50  tattoo_="%12.2f" %time.time()
51  time.sleep(0.05)
52  # si on espace deux créations de tatouages de 50 millisecondes
53  # il est impossible d'avoir deux tatouages identiques générés
54  # par le même ordinateur. Les chances que ça arrive avec des
55  # ordinateurs distincts sont minimes
56  outfile=open(tattooFileName,"w")
57  outfile.write(tattoo_)
58  outfile.close()
59  # on renvoie le nouveau tatouage
60  return tattoo_
61 
62 
66 
67 def editRecord(owd, hint=""):
68  ud=owd.getFat()
69  title=QApplication.translate("Dialog", "Choix du propriétaire", None)
70  prompt=QApplication.translate("Dialog", "Nouveau nom du propriétaire du baladeur", None)
71  newStudent, ok = QInputDialog.getText(None, title, prompt, text=hint)
72  if ok:
73  newStudent="%s" %newStudent
74  assert (ud.parent) # ud est une partition de type vfat
75  db.writeStudent(ud.stickid, ud.uuid, ud.tattoo(), newStudent)
76 
77 # une classe qui ajoute un nom de propriétaire aux disque USB,
78 # et qui en même temps ajoute des particularités selon le nom du
79 # vendeur et le modèle.
80 #
81 
83 
100 
101  def __init__(self, path, mp='', isUsb=False, vendor='', model='', parent=None,
102  fstype='', serial='', uuid='',
103  free=0, capacity=0, device='', firstFat=None, selected=True):
104  usbDisk2.uDisk2.__init__(self, path=path, mp=mp, isUsb=isUsb, vendor=vendor,
105  model=model, parent=parent, fstype=fstype, serial=serial,
106  uuid=uuid, free=free, capacity=capacity, device=device,
107  firstFat=firstFat, selected=selected)
108  QObject.__init__(self)
109  self.owner="" # le propriétaire est déterminé plus tard
110  self.visibleDirs=self.readQuirks()
111 
112 
115 
116  def getOwner(self):
117  return self.getFat().owner
118 
119 
122 
123  def getFat(self):
124  if self.parent:
125  return self
126  else:
127  return self.firstFat
128 
129 
132 
133  def valuableProperties(self,indent=4):
134  prefix="\n"+" "*indent
135  r=""
136  props=["mp", "parent", "fstype", "stickid", "uuid", "vendor", "model", "devStuff", "free", "capacity", "owner"]
137  for prop in props:
138  r+=prefix+"%s = %s" %(prop, getattr(self,prop))
139  return r
140 
141  # @return un identifiant unique, composé du nom du propriétaire
142  # suivi du tatouage
143  #
144 
145  def uniqueId(self):
146  return "%s~%s" %(self.owner, self.tattoo())
147 
148 
151 
152  def tattoo(self):
153  ud=self.getFat()
154  if ud and ud.mp:
155  return tattooInDir(ud.mp)
156  else:
157  return ""
158 
159  # Lit un dictionnaire indexé par le noms de vendeurs et les noms de modèle
160  # pour associer à ces modèles particuliers un répertoire visible.
161  # voir la fonction visibleDir. Ce dictionnaire est dans le fichier
162  # /usr/share/scolasync/marques.py ou dans ${HOME}/.scolasync/marques.py,
163  # (sous Linux) cette dernière place étant prépondérante.
164  #
165 
166  def readQuirks (self):
167  f1="/usr/share/scolasync/marques.py"
168  f2=os.path.expanduser(markFileName)
169  if os.path.exists(f2):
170  f=f2
171  else:
172  f=f1
173  result={}
174  try:
175  result=eval(open(f,"r", encoding="utf-8").read())
176  except:
177  pass
178  return result
179 
180  # Renvoie le répertoire particulier de la partition qui sera visible
181  # quand le baladeur est utilisé par son interface utilisateur. Ce
182  # répertoire peut varier selon les vendeurs et les modèles.
183  #
184 
185  def visibleDir(self):
186  k=self.vendor+":"+self.model
187  if k in self.visibleDirs.keys():
188  return self.visibleDirs[k]
189  else:
190  return "."
191 
192  # Méthode statique
193  # renvoie des titres pour les items obtenus par __getitem__
194  # la deuxième colonne sera toujours le propriétaire
195  # @param locale la locale, pour traduire les titres
196  # @return une liste de titres de colonnes
197  #
198 
199  def headers(locale="C"):
200  result=usbDisk2.uDisk2.headers(locale)
201  ownerProp=QApplication.translate("uDisk","owner",None)
202  result.insert(1,ownerProp)
203  return result
204 
205 
207 
208  def ownerByDb(self):
209  s=db.readStudent(self.stickid, self.uuid, self.tattoo())
210  if s != None:
211  return s
212  else:
213  return QApplication.translate("Dialog","inconnu",None)
214 
215  # renvoie un élément de listage de données internes au disque
216  # Fait en sorte que la deuxième colonne soit toujours le propriétaire
217  # @param n un nombre
218  # @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
219  #
220 
221  def __getitem__(self,n):
222  propListe=usbDisk2.uDisk2.headers()
223  if n == -1:
224  return self # pour accéder à toutes les données d'une partition
225  elif n==0:
226  return self.selected
227  elif n==1:
228  return self.ownerByDb()
229  else:
230  return self.unNumberProp(n)
231 
232 
233  headers = staticmethod(headers)
234 
235  # Demande un nom de propriétaire si celui-ci n'est pas encore défini
236  # pour cette clé USB. Enregistre au passage le nom du propriétaire
237  # dans les instances du disque et de sa partiton vfat
238  # @param ownerDialog si vrai : fait dialogue interactif
239  # @return un nom de propriétaire
240  #
241 
242  def ensureOwner(self, ownerDialog):
243  if self.parent and not self.mp : # partiton non montée
244  return
245  ud=self.getFat()
246  assert (ud.parent) # ud désigne une partition vfat
247  if not db.knowsId(ud.stickid, ud.uuid, ud.tattoo()) :
248  text=self.randomOwner(6)
249  if ownerDialog:
250  prompt=QApplication.translate("Dialog","La cle {id}<br>n'est pas identifiee, donnez le nom du proprietaire",None).format(id=ud.stickid)
251  title=QApplication.translate("Dialog","Entrer un nom",None)
252  text,ok = QInputDialog.getText(None, title, prompt)
253  db.writeStudent(ud.stickid, ud.uuid, ud.tattoo(), text)
254  o=db.readStudent(ud.stickid, ud.uuid, ud.tattoo())
255  self.owner=o
256  ud.owner=o
257  return o
258 
259 
263 
264  def randomOwner(self,length):
265  result="inconnu_"
266  for i in range(length):
267  result+=random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
268  return result
269 
270 # Une classe qui fournit une collection de disques USB connectés,
271 # avec leurs propriétaires. Les propriétaires sont recensés juste
272 # avant le montage des partions FAT.
273 #
274 
276 
277  # Le constructeur est un proxy pour usbDisk.Available.__init__
278  # qui force la classe de disques à utiliser : en effet ici
279  # uDisk désigne ownedUsbDisk.uDisk
280  # @param access le mode d'accès : 'disk' ou 'firstFat'
281  # @param diskClass la classe d'objets à créer pour chaque disque
282  # @param ownerDialog vrai si on veut qu'il y ait un dialogue automatique
283  # pour déterminer le propriétaire des disques non reconnus
284  #
285 
286  def __init__(self, access="disk", diskClass=uDisk2, ownerDialog=False):
287  self.ownerDialog=ownerDialog
288  usbDisk2.Available.__init__(self, access, diskClass)
289  # self.finishInit() # non! cette routine est déjà appelée par usbDisk2.Available.__init__
290 
291  # Fin de l'initialisation : trouve les propriétaires des disques
292  # puis identifie les partitions FAT et les monte
293  #
294 
295  def finishInit(self):
296  self.getFirstFats() # repère chaque partition FAT dans les instances des disques
297  for d in self.disks_ud():
298  d.owner=d.ensureOwner(self.ownerDialog)
299  self.mountFirstFats()
300 
301 
302 if __name__=="__main__":
303  from PyQt5.QtCore import *
304  from PyQt5.QtWidgets import *
305  import sys
307  def __init__(self):
308  QMainWindow.__init__(self)
309 
310  # The only thing in the app is a quit button
311  quitbutton = QPushButton('Examinez le terminal\nbranchez et débranchez des clés USB, puis\nQuittez', self)
312  quitbutton.clicked.connect(self.close)
313  self.setCentralWidget(quitbutton)
314 
315  machin=Available()
316  print (machin)
317  def print_targets_if_modif(man, obj):
318  if machin.modified:
319  print([s.split("/")[-1] for s in machin.targets.keys()])
320  for t in machin.targets:
321  machin.targets[t].owner=machin.targets[t].ownerByDb()
322  print (machin.targets[t].owner,":", t)
323  machin.modified=False
324  machin.addHook('object-added', print_targets_if_modif)
325  machin.addHook('object-removed', print_targets_if_modif)
326 
327  app = QApplication(sys.argv)
328  main = MainWindow()
329  main.show()
330  sys.exit(app.exec_())
331 
src.usbDisk2.uDisk2.unNumberProp
def unNumberProp(self, n)
Definition: usbDisk2.py:523
src.ownedUsbDisk.uDisk2.owner
owner
Definition: ownedUsbDisk.py:107
QObject
src.usbDisk2.uDisk2.uuid
uuid
Definition: usbDisk2.py:419
src.ownedUsbDisk.uDisk2.getFat
def getFat(self)
Renvoie à coup sûr la partition vfat d'un disque.
Definition: ownedUsbDisk.py:123
src.usbDisk2.Available.getFirstFats
def getFirstFats(self)
Definition: usbDisk2.py:734
src.ownedUsbDisk.print_targets_if_modif
def print_targets_if_modif(man, obj)
Definition: ownedUsbDisk.py:317
src.usbDisk2.uDisk2.stickid
stickid
Definition: usbDisk2.py:418
src.ownedUsbDisk.uDisk2.visibleDir
def visibleDir(self)
Definition: ownedUsbDisk.py:185
src.usbDisk2.Available
une classe pour représenter la collection des disques USB connectés
Definition: usbDisk2.py:583
src.ownedUsbDisk.Available.__init__
def __init__(self, access="disk", diskClass=uDisk2, ownerDialog=False)
Definition: ownedUsbDisk.py:286
src.ownedUsbDisk.Available
Definition: ownedUsbDisk.py:275
src.ownedUsbDisk.uDisk2.readQuirks
def readQuirks(self)
Definition: ownedUsbDisk.py:166
src.ownedUsbDisk.uDisk2.__getitem__
def __getitem__(self, n)
Renvoie un élément de listage de données internes au disque.
Definition: ownedUsbDisk.py:221
src.ownedUsbDisk.Available.finishInit
def finishInit(self)
Fin de l'initialisation.
Definition: ownedUsbDisk.py:295
src.usbDisk2.Available.disks_ud
def disks_ud(self)
Récolte les enregistrements de niveau supérieur de self.targets.
Definition: usbDisk2.py:657
src.ownedUsbDisk.uDisk2.uniqueId
def uniqueId(self)
Definition: ownedUsbDisk.py:145
src.usbDisk2.uDisk2.parent
parent
Definition: usbDisk2.py:416
src.usbDisk2.uDisk2.model
model
Definition: usbDisk2.py:415
src.ownedUsbDisk.uDisk2
Definition: ownedUsbDisk.py:82
src.usbDisk2.Available.mountFirstFats
def mountFirstFats(self)
Definition: usbDisk2.py:608
src.ownedUsbDisk.uDisk2.valuableProperties
def valuableProperties(self, indent=4)
Facilite l'accès aux propriétés intéressantes d'une instance.
Definition: ownedUsbDisk.py:133
src.ownedUsbDisk.uDisk2.ownerByDb
def ownerByDb(self)
renvoie un nom de propriétaire dans tous les cas.
Definition: ownedUsbDisk.py:208
src.ownedUsbDisk.uDisk2.randomOwner
def randomOwner(self, length)
fabrique un texte aléatoire de longueur donnée
Definition: ownedUsbDisk.py:264
src.ownedUsbDisk.Available.ownerDialog
ownerDialog
Definition: ownedUsbDisk.py:287
src.ownedUsbDisk.uDisk2.tattoo
def tattoo(self)
Renvoie un tatouage présent sur la clé, quitte à le créer.
Definition: ownedUsbDisk.py:152
QMainWindow
src.usbDisk2.uDisk2.mp
mp
Definition: usbDisk2.py:412
src.ownedUsbDisk.MainWindow
Definition: ownedUsbDisk.py:306
src.ownedUsbDisk.uDisk2.ensureOwner
def ensureOwner(self, ownerDialog)
Definition: ownedUsbDisk.py:242
src.usbDisk2.uDisk2.vendor
vendor
Definition: usbDisk2.py:414
src.usbDisk2.uDisk2.firstFat
firstFat
Definition: usbDisk2.py:423
src.ownedUsbDisk.tattooInDir
def tattooInDir(mountPoint)
Definition: ownedUsbDisk.py:41
QtCore
src.ownedUsbDisk.uDisk2.__init__
def __init__(self, path, mp='', isUsb=False, vendor='', model='', parent=None, fstype='', serial='', uuid='', free=0, capacity=0, device='', firstFat=None, selected=True)
Le constructeur.
Definition: ownedUsbDisk.py:101
src.usbDisk2.uDisk2
une classe pour représenter un disque ou une partition.
Definition: usbDisk2.py:390
src.ownedUsbDisk.editRecord
def editRecord(owd, hint="")
édition de la base de données.
Definition: ownedUsbDisk.py:67
src.ownedUsbDisk.uDisk2.visibleDirs
visibleDirs
Definition: ownedUsbDisk.py:108
src.usbDisk2.uDisk2.selected
selected
Definition: usbDisk2.py:424
src.ownedUsbDisk.uDisk2.headers
headers
Definition: ownedUsbDisk.py:233
QtWidgets
src.ownedUsbDisk.MainWindow.__init__
def __init__(self)
Definition: ownedUsbDisk.py:307
src.ownedUsbDisk.uDisk2.getOwner
def getOwner(self)
Renvoie le propriétaire.
Definition: ownedUsbDisk.py:116