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