950a4780357672763a6bfd5da81b5f5f783c103a
[minwii.git] / src / minwii / logapp.py
1 # -*- coding: utf-8 -*-
2 """
3 Interface graphique pour l'analyse des fichiers de log minwii.
4
5 $Id$
6 $URL$
7 """
8
9 from Tkinter import *
10 import tkFileDialog
11 from glob import glob
12 import os
13 from os.path import join as pjoin
14 from os.path import basename
15 from os.path import getsize
16 import os.path
17 from minwii.loganalyse import LogFileAnalyser
18 from pprint import pprint
19
20 class Application(Frame) :
21 def __init__(self, master=None) :
22 Frame.__init__(self, master)
23 self.configureStretching()
24 self.createWidgets()
25 self.logDir = ''
26 self.logFiles = []
27 self.resultsFrame = None
28
29 # debug
30 #self.chooseDirDialog(dir='/Users/pinbe/minwii_logs')
31
32 def configureStretching(self) :
33 top=self.winfo_toplevel()
34 top.rowconfigure(0, weight=1)
35 top.columnconfigure(0, weight=1)
36
37 self.grid(sticky=N+S+E+W, padx=10, pady=10)
38 self.rowconfigure(0, weight=1)
39 self.columnconfigure(0, weight=1)
40
41 def createWidgets(self) :
42 # zone d'affichage des données'
43 self.dataFrame = df = Frame(self)
44
45 self.identFrame = Identification(df)
46 self.identFrame.grid(sticky=NW)
47
48 # barre de boutons
49 self.btnFrame = bf = Frame(self)
50 bf.grid(row=1, column=0, sticky=W+S+E)
51 bf.rowconfigure(0, weight=1)
52 for i in range(3) :
53 bf.columnconfigure(i, weight=1)
54
55 self.chooseLogDir = Button(bf, text="Parcourir…", command=self.chooseDirDialog)
56 self.chooseLogDir.grid(row=0, column=0, sticky=W)
57
58 self.nav = Navbar(bf, incCallback=self.loadLogFile, decCallback=self.loadLogFile)
59
60 self.quitButton = Button(bf, text='Terminer', command=self.quit)
61 self.quitButton.grid(row=0, column=2, sticky=E)
62
63 def chooseDirDialog(self, dir=None) :
64 if dir is None :
65 self.logDir = tkFileDialog.askdirectory(title='Sélectionnez un dossier de fichiers de logs')
66 else :
67 self.logDir = dir
68 if self.logDir :
69 self.logFiles = glob(pjoin(self.logDir, '*.log'))
70 self._cleanupJunkFiles()
71 self.logFiles.sort()
72 self.logFiles.reverse()
73 self.dataFrame.grid(row=0, column=0, sticky=NW)
74 self.nav.setSize(len(self.logFiles))
75 self.nav.grid(row=0, column=1)
76 self.loadLogFile(self.nav)
77
78 def _cleanupJunkFiles(self) :
79 files = []
80 while self.logFiles :
81 f = self.logFiles.pop()
82 if not getsize(f) :
83 os.remove(f)
84 continue
85 else :
86 of = open(f)
87 lfa = LogFileAnalyser(of)
88 if lfa.getLastEventTicks() is None :
89 of.close()
90 os.remove(f)
91 continue
92 else :
93 of.close()
94
95 files.append(f)
96
97 self.logFiles = files
98
99
100 def loadLogFile(self, nav) :
101 index = nav.index - 1
102 filepath = self.logFiles[index]
103 filename = basename(filepath)
104 self.identFrame.setFileName(filename)
105 if self.resultsFrame :
106 self.resultsFrame.destroy()
107 self.resultsFrame = ResultsFrame(self.dataFrame, filepath)
108 self.resultsFrame.layResults()
109 self.resultsFrame.grid()
110
111
112 class Navbar(Frame) :
113 def __init__(self, master=None, size=1, incCallback=None, decCallback=None) :
114 Frame.__init__(self, master)
115 self.caption = StringVar()
116 self.createWidgets()
117 self.setSize(size)
118 self.incCallback = incCallback if incCallback else lambda x : None
119 self.decCallback = decCallback if decCallback else lambda x : None
120 self.caption.set('%d / %d' % (self.index, self.to))
121
122 def createWidgets(self) :
123 self.backBtn = Button(self,
124 text='◀',
125 command = self.dec
126 )
127 self.backBtn.grid(row=0, column=0)
128
129 self.lbl = Label(self, textvariable=self.caption)
130 self.lbl.grid(row=0, column=1)
131
132 self.nextBtn = Button(self,
133 text='▶',
134 command = self.inc)
135 self.nextBtn.grid(row=0, column=2)
136
137 def refreshStates(self) :
138 if self.index == self.from_ :
139 self.backBtn.configure(state=DISABLED)
140 else :
141 self.backBtn.configure(state=NORMAL)
142
143 if self.index < self.to :
144 self.nextBtn.configure(state=NORMAL)
145 else :
146 self.nextBtn.configure(state=DISABLED)
147
148 self.caption.set('%d / %d' % (self.index, self.to))
149
150
151 def dec(self) :
152 self.index = self.index - 1
153 self.refreshStates()
154 self.decCallback(self)
155
156 def inc(self) :
157 self.index = self.index + 1
158 self.refreshStates()
159 self.incCallback(self)
160
161 def setSize(self, size) :
162 self.from_ = 1
163 self.to = size
164 self.index = 1
165 self.refreshStates()
166
167
168 class Identification(Frame) :
169 def __init__(self, master=None) :
170 Frame.__init__(self, master)
171 self.fileName = StringVar()
172 self.createWidgets()
173
174 def setFileName(self, name) :
175 self.fileName.set(name)
176
177 def createWidgets(self) :
178 fileLbl = Label(self, text='Fichier :')
179 fileLbl.grid(row=0, column=0, sticky=E)
180
181 fileNameLbl = Label(self, textvariable=self.fileName)
182 fileNameLbl.grid(row=0, column=1, sticky=W)
183
184 nameLbl = Label(self, text='Patient :')
185 nameLbl.grid(row=1, column=0, sticky=E)
186
187 self.nameEntry = Entry(self, width=40)
188 self.nameEntry.grid(row=1, column=1, sticky=W)
189
190 commentsLbl = Label(self, text='Commentaires :')
191 commentsLbl.grid(row=2, column=0, sticky=E)
192
193 self.commentsText = Text(self, width=40, height=4, undo=True, wrap=WORD)
194 self.commentsText.grid(row=2, column=1, sticky=W)
195
196 class ResultsFrame(Frame) :
197 def __init__(self, master, logFilePath) :
198 Frame.__init__(self, master)
199 self.logFilePath = logFilePath
200
201 def layResults(self) :
202 lfa = LogFileAnalyser(self.logFilePath)
203 results = lfa.analyse()
204 if results :
205 for i, kv in enumerate(results) :
206 k, v = kv
207 kl = Label(self, text='%s :' % k)
208 kl.grid(row=i, column=0, sticky=E)
209
210 vl = Label(self, text=v)
211 vl.grid(row=i, column=1, sticky=W)
212 else :
213 msg = Label(self, text="Pas de données exploitables.")
214 msg.grid()
215
216
217
218 app = Application()
219 app.master.title("Analyseur des sessions MINWii")
220 app.mainloop()