1 # -*- coding: utf-8 -*-
3 Interface graphique pour l'analyse des fichiers de log minwii.
10 os
.environ
['WINWII_NO_LOG'] = '1'
14 from os
.path
import join
as pjoin
15 from os
.path
import basename
16 from os
.path
import getsize
18 from minwii
.loganalyse
import LogFileAnalyser
19 from minwii
.config
import LOGS_DIR
20 from pprint
import pprint
22 class Application(Frame
) :
23 def __init__(self
, master
=None) :
24 Frame
.__init
__(self
, master
)
25 self
.configureStretching()
29 self
.currentFilePath
= ''
30 self
.resultsFrame
= None
32 if os
.path
.exists(LOGS_DIR
) :
33 self
.chooseDirDialog(dir=LOGS_DIR
)
35 def configureStretching(self
) :
36 top
=self
.winfo_toplevel()
37 top
.rowconfigure(0, weight
=1)
38 top
.columnconfigure(0, weight
=1)
40 self
.grid(sticky
=N
+S
+E
+W
, padx
=10, pady
=10)
41 self
.rowconfigure(0, weight
=1)
42 self
.columnconfigure(0, weight
=1)
44 def createWidgets(self
) :
45 # zone d'affichage des données'
46 self
.dataFrame
= df
= Frame(self
)
48 self
.identFrame
= Identification(df
)
49 self
.identFrame
.grid(sticky
=NW
)
52 self
.btnFrame
= bf
= Frame(self
)
53 bf
.grid(row
=1, column
=0, sticky
=W
+S
+E
)
54 bf
.rowconfigure(0, weight
=1)
56 bf
.columnconfigure(i
, weight
=1)
58 self
.chooseLogDir
= Button(bf
, text
="Parcourir…", command
=self
.chooseDirDialog
)
59 self
.chooseLogDir
.grid(row
=0, column
=0, sticky
=W
)
61 self
.nav
= Navbar(bf
, incCallback
=self
.loadLogFile
, decCallback
=self
.loadLogFile
)
63 self
.quitButton
= Button(bf
, text
='Terminer', command
=self
.quit
)
64 self
.quitButton
.grid(row
=0, column
=2, sticky
=E
)
66 def chooseDirDialog(self
, dir=None) :
68 self
.logDir
= tkFileDialog
.askdirectory(title
='Sélectionnez un dossier de fichiers de logs')
72 self
.logFiles
= glob(pjoin(self
.logDir
, '*.log'))
73 self
._cleanupJunkFiles
()
75 self
.logFiles
.reverse()
76 self
.dataFrame
.grid(row
=0, column
=0, sticky
=NW
)
77 self
.nav
.setSize(len(self
.logFiles
))
78 self
.nav
.grid(row
=0, column
=1)
79 self
.loadLogFile(self
.nav
)
81 def _cleanupJunkFiles(self
) :
84 f
= self
.logFiles
.pop()
90 lfa
= LogFileAnalyser(of
)
91 if lfa
.getLastEventTicks() is None :
100 self
.logFiles
= files
103 def loadLogFile(self
, nav
) :
104 index
= nav
.index
- 1
105 filepath
= self
.logFiles
[index
]
106 self
.currentFilePath
= filepath
107 lfa
= LogFileAnalyser(self
.currentFilePath
)
108 self
.identFrame
.refresh(lfa
)
109 if self
.resultsFrame
:
110 self
.resultsFrame
.destroy()
111 self
.resultsFrame
= ResultsFrame(self
.dataFrame
)
112 self
.resultsFrame
.layResults(lfa
)
114 self
.resultsFrame
.grid()
117 class Navbar(Frame
) :
118 def __init__(self
, master
=None, size
=1, incCallback
=None, decCallback
=None) :
119 Frame
.__init
__(self
, master
)
120 self
.caption
= StringVar()
123 self
.incCallback
= incCallback
if incCallback
else lambda x
: None
124 self
.decCallback
= decCallback
if decCallback
else lambda x
: None
125 self
.caption
.set('%d / %d' % (self
.index
, self
.to
))
127 def createWidgets(self
) :
128 self
.backBtn
= Button(self
,
132 self
.backBtn
.grid(row
=0, column
=0)
134 self
.lbl
= Label(self
, textvariable
=self
.caption
)
135 self
.lbl
.grid(row
=0, column
=1)
137 self
.nextBtn
= Button(self
,
140 self
.nextBtn
.grid(row
=0, column
=2)
142 def refreshStates(self
) :
143 if self
.index
== self
.from_
:
144 self
.backBtn
.configure(state
=DISABLED
)
146 self
.backBtn
.configure(state
=NORMAL
)
148 if self
.index
< self
.to
:
149 self
.nextBtn
.configure(state
=NORMAL
)
151 self
.nextBtn
.configure(state
=DISABLED
)
153 self
.caption
.set('%d / %d' % (self
.index
, self
.to
))
157 self
.index
= self
.index
- 1
159 self
.decCallback(self
)
162 self
.index
= self
.index
+ 1
164 self
.incCallback(self
)
166 def setSize(self
, size
) :
173 class Identification(Frame
) :
174 def __init__(self
, master
=None) :
175 Frame
.__init
__(self
, master
)
176 self
.fileName
= StringVar()
177 self
.hid
= StringVar()
178 self
.patientName
= StringVar()
181 def refresh(self
, lfa
) :
182 filename
= basename(lfa
.logfile
.name
)
183 self
.fileName
.set(filename
)
184 self
.hid
.set(lfa
.getHID())
185 metadata
= lfa
.getMetadata()
186 self
.patientName
.set(metadata
.get('PatientName', ''))
187 self
.commentsText
.delete(1.0, END
)
188 self
.commentsText
.insert(1.0, metadata
.get('Comments', ''))
190 def createWidgets(self
) :
191 fileLbl
= Label(self
, text
='Fichier :')
192 fileLbl
.grid(row
=0, column
=0, sticky
=E
)
194 fileNameLbl
= Label(self
, textvariable
=self
.fileName
)
195 fileNameLbl
.grid(row
=0, column
=1, sticky
=W
)
197 hidLbl
= Label(self
, text
='HID :')
198 hidLbl
.grid(row
=1, column
=0, sticky
=E
)
200 hidNameLbl
= Label(self
, textvariable
=self
.hid
)
201 hidNameLbl
.grid(row
=1, column
=1, sticky
=W
)
203 nameLbl
= Label(self
, text
='Patient :')
204 nameLbl
.grid(row
=2, column
=0, sticky
=E
)
206 self
.nameEntry
= Entry(self
, width
=40, textvariable
=self
.patientName
)
207 self
.nameEntry
.grid(row
=2, column
=1, sticky
=W
)
209 commentsLbl
= Label(self
, text
='Commentaires :')
210 commentsLbl
.grid(row
=3, column
=0, sticky
=E
)
212 self
.commentsText
= Text(self
, width
=40, height
=4, undo
=True, wrap
=WORD
)
213 self
.commentsText
.grid(row
=3, column
=1, sticky
=W
)
215 self
.saveBtn
= Button(self
, text
='Enregistrer', command
=self
.saveMetadata
)
216 self
.saveBtn
.grid(row
=4, column
=1, sticky
=E
)
218 def saveMetadata(self
):
219 app
= self
.master
.master
220 filepath
= app
.currentFilePath
221 lfa
= LogFileAnalyser(filepath
, mode
='r+')
222 patientName
= '%s\n' % self
.nameEntry
.get().replace('\n', ' ').strip()
223 comments
= '%s\n' % self
.commentsText
.get(1.0, END
).replace('\n', ' ').strip()
224 metadata
= (('PatientName', self
.nameEntry
.get()),
225 ('Comments', comments
))
226 lfa
.setMetadata(metadata
)
229 class ResultsFrame(Frame
) :
231 def layResults(self
, lfa
) :
232 results
= lfa
.analyse()
234 for i
, kvt
in enumerate(results
) :
235 k
, v
, timeBased
= kvt
236 kl
= Label(self
, text
='%s :' % k
)
237 kl
.grid(row
=i
, column
=0, sticky
=E
)
240 vl
= Label(self
, text
=v
)
241 vl
.grid(row
=i
, column
=1, sticky
=W
)
246 c
= Canvas(self
, background
='#fff', width
=cw
, height
=ch
)
247 rectW
= int(float(cw
) / len(v
))
248 unitRectH
= float(ch
) / maxv
249 for j
, fv
in enumerate(v
) :
252 y0
= ch
- int(unitRectH
* fv
)
255 c
.create_rectangle(x0
, y0
, x1
, y1
, fill
="#9085ba")
256 c
.grid(row
=i
, column
=1, sticky
=W
)
259 vl
= Label(self
, text
='—')
260 vl
.grid(row
=i
, column
=1, sticky
=W
)
262 msg
= Label(self
, text
="Pas de données exploitables.")
268 app
.master
.title("Analyseur des sessions MINDs")
271 if __name__
== '__main__' :