ScolaSync: Fichier source de src/ownedUsbDisk.py

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 ##
36 #
37 # Renvoie le tatouage pour un point de montage donné, quitte à le créer
38 # si nécessaire.
39 # @param mountPoint un point de montage de partition
40 # @return le tatouage
41 #
42 def tattooInDir(mountPoint):
43 tattooFileName = os.path.join(mountPoint,".scolasync-tattoo")
44 tattoo_=""
45 if os.path.exists(tattooFileName):
46 tattoo_=open(tattooFileName,"r").readlines()[0].strip()
47 if tattoo_ != "" :
48 # le tatouage existe déjà, on renvoie sa valeur
49 return tattoo_
50 else:
51 tattoo_="%12.2f" %time.time()
52 time.sleep(0.05)
53 # si on espace deux créations de tatouages de 50 millisecondes
54 # il est impossible d'avoir deux tatouages identiques générés
55 # par le même ordinateur. Les chances que ça arrive avec des
56 # ordinateurs distincts sont minimes
57 outfile=open(tattooFileName,"w")
58 outfile.write(tattoo_)
59 outfile.close()
60 # on renvoie le nouveau tatouage
61 return tattoo_
62
63 ##
64 #
65 # édition de la base de données
66 # @param owd une instance de ownedUsbDisk
67 # @param hint chaîne vide par défaut. Peut être le nom de l'ancien propriétaire
68 #
69 def editRecord(owd, hint=""):
70 ud=owd.getFat()
71 title=QApplication.translate("Dialog", "Choix du propriétaire", None)
72 prompt=QApplication.translate("Dialog", "Nouveau nom du propriétaire du baladeur", None)
73 newStudent, ok = QInputDialog.getText(None, title, prompt, text=hint)
74 if ok:
75 newStudent="%s" %newStudent
76 assert (ud.parent) # ud est une partition de type vfat
77 db.writeStudent(ud.stickid, ud.uuid, ud.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 #
85 class uDisk2(usbDisk2.uDisk2,QObject):
86 ##
87 #
88 # Le constructeur
89 # @param path un chemin comme '/org/freedesktop/UDisks2/block_devices/sdX'
90 # @param mp point de montage ('' par défaut)
91 # @param isUsb en général, vrai vu qu'on se s'intéressera qu'à des périphériques
92 # USB
93 # @param vendor indication de vendeur
94 # @param model indication de modèle
95 # @param parent périphérique parent (None par défaut)
96 # @param fstype type de système de fichiers
97 # @param serial numéro de série
98 # @param uuid identifiant donné au disque lors du formatage
99 # @param free taille de la zone libre pour l'écriture
100 # @param capacity taille du périphérique
101 # @param device pseudo-fichier pour l'accès au périphérique
102 # @param firstFat une instance de uDisk2, de type vfat parmi les partitions
103 # @param selected vrai/faux selon qu'on sélectionne ou non le périphérique (vrai par défaut)
104 #
105 def __init__(self, path, mp='', isUsb=False, vendor='', model='', parent=None,
106 fstype='', serial='', uuid='',
107 free=0, capacity=0, device='', firstFat=None, selected=True):
108 usbDisk2.uDisk2.__init__(self, path=path, mp=mp, isUsb=isUsb, vendor=vendor,
109 model=model, parent=parent, fstype=fstype, serial=serial,
110 uuid=uuid, free=free, capacity=capacity, device=device,
111 firstFat=firstFat, selected=selected)
112 QObject.__init__(self)
113 self.owner="" # le propriétaire est déterminé plus tard
114 self.visibleDirs=self.readQuirks()
115
116 ##
117 #
118 # Renvoie le propriétaire
119 # @return le propriétaire de la clé
120 #
121 def getOwner(self):
122 return self.getFat().owner
123
124 ##
125 #
126 # Renvoie à coup sûr la partition vfat d'un disque
127 # @return une instance uDisk2 représentant une partition vfat
128 #
129 def getFat(self):
130 if self.parent:
131 return self
132 else:
133 return self.firstFat
134
135 ##
136 #
137 # Facilite l'accès aux propriétés intéressantes d'une instance
138 # @return une chaîne indentée avec les propriétés intéressantes, une par ligne
139 #
140 def valuableProperties(self,indent=4):
141 prefix="\n"+" "*indent
142 r=""
143 props=["mp", "parent", "fstype", "stickid", "uuid", "vendor", "model", "devStuff", "free", "capacity", "owner"]
144 for prop in props:
145 r+=prefix+"%s = %s" %(prop, getattr(self,prop))
146 return r
147
148 ##
149 #
150 # @return un identifiant unique, composé du nom du propriétaire
151 # suivi du tatouage
152 #
153 def uniqueId(self):
154 return "%s~%s" %(self.owner, self.tattoo())
155
156 ##
157 #
158 # Renvoie un tatouage présent sur la clé, quitte à le créer.
159 # @result un tatouage, supposément unique.
160 #
161 def tattoo(self):
162 ud=self.getFat()
163 if ud and ud.mp:
164 return tattooInDir(ud.mp)
165 else:
166 return ""
167
168 ##
169 #
170 # Lit un dictionnaire indexé par le noms de vendeurs et les noms de modèle
171 # pour associer à ces modèles particuliers un répertoire visible.
172 # voir la fonction visibleDir. Ce dictionnaire est dans le fichier
173 # /usr/share/scolasync/marques.py ou dans ${HOME}/.scolasync/marques.py,
174 # (sous Linux) cette dernière place étant prépondérante.
175 #
176 def readQuirks (self):
177 f1="/usr/share/scolasync/marques.py"
178 f2=os.path.expanduser(markFileName)
179 if os.path.exists(f2):
180 f=f2
181 else:
182 f=f1
183 result=eval(open(f,"r", encoding="utf-8").read())
184 return result
185
186 ##
187 #
188 # Renvoie le répertoire particulier de la partition qui sera visible
189 # quand le baladeur est utilisé par son interface utilisateur. Ce
190 # répertoire peut varier selon les vendeurs et les modèles.
191 #
192 def visibleDir(self):
193 k=self.vendor+":"+self.model
194 if k in self.visibleDirs.keys():
195 return self.visibleDirs[k]
196 else:
197 return "."
198
199 ##
200 #
201 # Méthode statique
202 # renvoie des titres pour les items obtenus par __getitem__
203 # la deuxième colonne sera toujours le propriétaire
204 # @param locale la locale, pour traduire les titres
205 # @return une liste de titres de colonnes
206 #
207 def headers(locale="C"):
208 result=usbDisk2.uDisk2.headers(locale)
209 ownerProp=QApplication.translate("uDisk","owner",None)
210 result.insert(1,ownerProp)
211 return result
212
213 ##
214 #
215 # renvoie un nom de propriétaire dans tous les cas.
216 #
217 def ownerByDb(self):
218 s=db.readStudent(self.stickid, self.uuid, self.tattoo())
219 if s != None:
220 return s
221 else:
222 return QApplication.translate("Dialog","inconnu",None)
223
224 ##
225 #
226 # renvoie un élément de listage de données internes au disque
227 # Fait en sorte que la deuxième colonne soit toujours le propriétaire
228 # @param n un nombre
229 # @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
230 #
231 def __getitem__(self,n):
232 propListe=usbDisk2.uDisk2.headers()
233 if n == -1:
234 return self # pour accéder à toutes les données d'une partition
235 elif n==0:
236 return self.selected
237 elif n==1:
238 return self.ownerByDb()
239 else:
240 return self.unNumberProp(n)
241
242
243 headers = staticmethod(headers)
244
245 ##
246 #
247 # Demande un nom de propriétaire si celui-ci n'est pas encore défini
248 # pour cette clé USB. Enregistre au passage le nom du propriétaire
249 # dans les instances du disque et de sa partiton vfat
250 # @param ownerDialog si vrai : fait dialogue interactif
251 # @return un nom de propriétaire
252 #
253 def ensureOwner(self, ownerDialog):
254 if self.parent and not self.mp : # partiton non montée
255 return
256 ud=self.getFat()
257 assert (ud.parent) # ud désigne une partition vfat
258 if not db.knowsId(ud.stickid, ud.uuid, ud.tattoo()) :
259 text=self.randomOwner(6)
260 if ownerDialog:
261 prompt=QApplication.translate("Dialog","La cle {id}<br>n'est pas identifiee, donnez le nom du proprietaire",None).format(id=ud.stickid)
262 title=QApplication.translate("Dialog","Entrer un nom",None)
263 text,ok = QInputDialog.getText(None, title, prompt)
264 db.writeStudent(ud.stickid, ud.uuid, ud.tattoo(), text)
265 o=db.readStudent(ud.stickid, ud.uuid, ud.tattoo())
266 self.owner=o
267 ud.owner=o
268 return o
269
270 ##
271 #
272 # fabrique un texte aléatoire de longueur donnée
273 # @param length la longueur recherchée
274 # @return un texte pseudo-aléatoire
275 #
276 def randomOwner(self,length):
277 result="inconnu_"
278 for i in range(length):
279 result+=random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
280 return result
281
282 ##
283 #
284 # Une classe qui fournit une collection de disques USB connectés,
285 # avec leurs propriétaires. Les propriétaires sont recensés juste
286 # avant le montage des partions FAT.
287 #
288 class Available(usbDisk2.Available):
289
290 ##
291 #
292 # Le constructeur est un proxy pour usbDisk.Available.__init__
293 # qui force la classe de disques à utiliser : en effet ici
294 # uDisk désigne ownedUsbDisk.uDisk
295 # @param access le mode d'accès : 'disk' ou 'firstFat'
296 # @param diskClass la classe d'objets à créer pour chaque disque
297 # @param ownerDialog vrai si on veut qu'il y ait un dialogue automatique
298 # pour déterminer le propriétaire des disques non reconnus
299 #
300 def __init__(self, access="disk", diskClass=uDisk2, ownerDialog=False):
301 self.ownerDialog=ownerDialog
302 usbDisk2.Available.__init__(self, access, diskClass)
303 # self.finishInit() # non! cette routine est déjà appelée par usbDisk2.Available.__init__
304
305 ##
306 #
307 # Fin de l'initialisation : trouve les propriétaires des disques
308 # puis identifie les partitions FAT et les monte
309 #
310 def finishInit(self):
311 self.getFirstFats() # repère chaque partition FAT dans les instances des disques
312 for d in self.disks_ud():
313 d.owner=d.ensureOwner(self.ownerDialog)
314 self.mountFirstFats()
315
316
317 if __name__=="__main__":
318 from PyQt5.QtCore import *
319 from PyQt5.QtWidgets import *
320 import sys
321 class MainWindow(QMainWindow):
322 def __init__(self):
323 QMainWindow.__init__(self)
324
325 # The only thing in the app is a quit button
326 quitbutton = QPushButton('Examinez le terminal\nbranchez et débranchez des clés USB, puis\nQuittez', self)
327 quitbutton.clicked.connect(self.close)
328 self.setCentralWidget(quitbutton)
329
330 machin=Available()
331 print (machin)
332 def print_targets_if_modif(man, obj):
333 if machin.modified:
334 print([s.split("/")[-1] for s in machin.targets.keys()])
335 for t in machin.targets:
336 machin.targets[t].owner=machin.targets[t].ownerByDb()
337 print (machin.targets[t].owner,":", t)
338 machin.modified=False
339 machin.addHook('object-added', print_targets_if_modif)
340 machin.addHook('object-removed', print_targets_if_modif)
341
342 app = QApplication(sys.argv)
343 main = MainWindow()
344 main.show()
345 sys.exit(app.exec_())
346
src.usbDisk2.uDisk2.uuid
uuid
Definition: usbDisk2.py:427
src.ownedUsbDisk.uDisk2.getOwner
def getOwner(self)
Renvoie le propriétaire.
Definition: ownedUsbDisk.py:121
src.ownedUsbDisk.uDisk2.getFat
def getFat(self)
Renvoie à coup sûr la partition vfat d'un disque.
Definition: ownedUsbDisk.py:129
src.ownedUsbDisk.uDisk2.__init__
def __init__
Le constructeur.
Definition: ownedUsbDisk.py:107
src.usbDisk2.uDisk2
une classe pour représenter un disque ou une partition.
Definition: usbDisk2.py:395
QtCore
QtWidgets
src.ownedUsbDisk.Available.__init__
def __init__
Le constructeur est un proxy pour usbDisk.Available.__init__ qui force la classe de disques à utilise...
Definition: ownedUsbDisk.py:300
src.ownedUsbDisk.uDisk2.owner
owner
Definition: ownedUsbDisk.py:113
src.ownedUsbDisk.MainWindow.__init__
def __init__(self)
Definition: ownedUsbDisk.py:322
src.ownedUsbDisk.Available.ownerDialog
ownerDialog
Definition: ownedUsbDisk.py:301
src.ownedUsbDisk.Available
Une classe qui fournit une collection de disques USB connectés, avec leurs propriétaires.
Definition: ownedUsbDisk.py:288
src.ownedUsbDisk.uDisk2.readQuirks
def readQuirks(self)
Lit un dictionnaire indexé par le noms de vendeurs et les noms de modèle pour associer à ces modèles ...
Definition: ownedUsbDisk.py:176
src.usbDisk2.uDisk2.parent
parent
Definition: usbDisk2.py:424
QObject
src.ownedUsbDisk.print_targets_if_modif
def print_targets_if_modif(man, obj)
Definition: ownedUsbDisk.py:332
src.ownedUsbDisk.uDisk2.visibleDir
def visibleDir(self)
Renvoie le répertoire particulier de la partition qui sera visible quand le baladeur est utilisé par ...
Definition: ownedUsbDisk.py:192
src.usbDisk2.uDisk2.mp
mp
Definition: usbDisk2.py:420
src.ownedUsbDisk.uDisk2.__getitem__
def __getitem__(self, n)
renvoie un élément de listage de données internes au disque Fait en sorte que la deuxième colonne soi...
Definition: ownedUsbDisk.py:231
src.usbDisk2.uDisk2.stickid
stickid
Definition: usbDisk2.py:426
src.ownedUsbDisk.editRecord
def editRecord
édition de la base de données.
Definition: ownedUsbDisk.py:69
src.usbDisk2.uDisk2.model
model
Definition: usbDisk2.py:423
src.ownedUsbDisk.uDisk2.uniqueId
def uniqueId(self)
Definition: ownedUsbDisk.py:153
src.ownedUsbDisk.Available.finishInit
def finishInit(self)
Fin de l'initialisation : trouve les propriétaires des disques puis identifie les partitions FAT et l...
Definition: ownedUsbDisk.py:310
src.ownedUsbDisk.uDisk2.ownerByDb
def ownerByDb(self)
renvoie un nom de propriétaire dans tous les cas.
Definition: ownedUsbDisk.py:217
src.ownedUsbDisk.uDisk2.headers
tuple headers
Definition: ownedUsbDisk.py:243
src.ownedUsbDisk.uDisk2.ensureOwner
def ensureOwner(self, ownerDialog)
Demande un nom de propriétaire si celui-ci n'est pas encore défini pour cette clé USB...
Definition: ownedUsbDisk.py:253
src.ownedUsbDisk.uDisk2.randomOwner
def randomOwner(self, length)
fabrique un texte aléatoire de longueur donnée
Definition: ownedUsbDisk.py:276
src.usbDisk2.Available.getFirstFats
def getFirstFats(self)
Facilite l'accès aux partitions de type DOS-FAT, et a des effets de bord :
Definition: usbDisk2.py:758
src.ownedUsbDisk.uDisk2.valuableProperties
def valuableProperties
Facilite l'accès aux propriétés intéressantes d'une instance.
Definition: ownedUsbDisk.py:140
src.ownedUsbDisk.uDisk2.tattoo
def tattoo(self)
Renvoie un tatouage présent sur la clé, quitte à le créer.
Definition: ownedUsbDisk.py:161
src.ownedUsbDisk.MainWindow
Definition: ownedUsbDisk.py:321
QMainWindow
src.usbDisk2.Available
une classe pour représenter la collection des disques USB connectés
Definition: usbDisk2.py:592
src.ownedUsbDisk.tattooInDir
def tattooInDir(mountPoint)
Renvoie le tatouage pour un point de montage donné, quitte à le créer si nécessaire.
Definition: ownedUsbDisk.py:42
src.usbDisk2.uDisk2.firstFat
firstFat
Definition: usbDisk2.py:431
src.usbDisk2.uDisk2.selected
selected
Definition: usbDisk2.py:432
src.usbDisk2.uDisk2.unNumberProp
def unNumberProp(self, n)
retire le numéro des en-têtes pour en faire un nom de propriété valide pour interroger dbus ...
Definition: usbDisk2.py:529
src.usbDisk2.Available.disks_ud
def disks_ud(self)
Récolte les enregistrements de niveau supérieur de self.targets.
Definition: usbDisk2.py:675
src.ownedUsbDisk.uDisk2.visibleDirs
visibleDirs
Definition: ownedUsbDisk.py:114
src.ownedUsbDisk.uDisk2
une classe qui ajoute un nom de propriétaire aux disque USB, et qui en même temps ajoute des particul...
Definition: ownedUsbDisk.py:85
src.usbDisk2.Available.mountFirstFats
def mountFirstFats(self)
fabrique la liste des partitions FAT, monte les partitions FAT si elles ne le sont pas ...
Definition: usbDisk2.py:620
src.usbDisk2.uDisk2.vendor
vendor
Definition: usbDisk2.py:422