#!/usr/bin/python
# -*- coding: ISO-8859-15 -*-
from os import walk
from re import compile, findall
from threading import Thread
from Tkinter import *
from Tkconstants import *
DEFAULT_BUFSIZE = 8*1024
#
# Thread de recherche
#
class Recherche(Thread):
""" Thread de recherche de texte
"""
def __init__(self, chemin, texte, pourcent, retour):
Thread.__init__(self)
self.chemin = chemin
self.texte = texte
self.pourcent = pourcent
self.retour = retour
self.tampon = DEFAULT_BUFSIZE
self.running = False
def stop(self):
""" arrête le thread """
if self.running:
self.running = False
self.join()
def run(self):
""" méthode lancée par start() """
chemin = self.chemin
texte = self.texte
trouve = 0
self.running = True
for racine, reps, fichiers in walk(chemin):
if not self.running:
break
i = 1
for fichier in fichiers:
if not self.running:
break
self.pourcent('Recherche: %s/%s : %d/%d' \
% (racine, fichier, i, len(fichiers)))
nom_complet = '%s/%s' %(racine, fichier)
if self.texte_present(nom_complet, texte):
self.retour('%s' % nom_complet)
trouve += 1
i += 1
if trouve == 0:
self.retour('Aucun fichier')
self.pourcent('%d fichier(s) trouvé(s)' % trouve)
def texte_present(self, fichier, texte):
""" renvoie vrai si le fichier contient le texte """
c_cherche = compile(texte)
try:
curseur = open(fichier, 'r', buffering=self.tampon)
except IOError?: # en cas de pb d'accès (droits, etc.)
return False
try:
line = None
while line != '':
if not self.running:
return False
line = curseur.readline(self.tampon)
res = findall(c_cherche, line)
if res != []?:
return True
return False
finally:
curseur.close()
#
# Frames
#
class FrameChemin?(Frame):
def __init__(self, racine):
Frame.__init__(self)
label = Label(self, text="Chemin de recherche")
label.pack(fill=X, expand=1)
self.chemin = Entry(self, name="chemin")
self.chemin.pack(fill=BOTH)
self.chemin.insert(0, '/')
self.chemin.select_range(0, END)
class FrameTexte?(Frame):
def __init__(self, racine):
Frame.__init__(self)
self.label = Label(self, text="Texte à rechercher")
self.label.pack(fill=X, expand=1)
self.texte = Entry(self, name="texte")
self.texte.pack(fill=BOTH)
self.texte.insert(0, '')
self.texte.select_range(0, END)
class FrameButton?(Frame):
def __init__(self, racine):
Frame.__init__(self)
def create_elements(self, stop_command, search_command,
close_command):
self.button = Button(self,text="Stop",
command=stop_command)
self.button.pack(side=RIGHT, padx=5, pady=5)
self.button = Button(self,text="Rechercher",
command=search_command)
self.button.pack(side=RIGHT, padx=5, pady=5)
self.button3 = Button(self,text="Fermer",
command=close_command)
self.button3.pack(side=RIGHT)
class FrameResultat?(Frame):
def __init__(self, racine):
Frame.__init__(self)
self.fenetre_resultats = Listbox(self)
self.resultats_ascenseur = Scrollbar(self, orient=VERTICAL,
command=self.fenetre_resultats.yview)
self.fenetre_resultats.config(yscrollcommand=\
self.resultats_ascenseur.set)
self.fenetre_resultats.pack(side=LEFT, expand=1, fill=BOTH)
self.resultats_ascenseur.pack(side=RIGHT, fill=Y)
#
# Application
#
class Application(object):
""" Frame contenant l'interface de recherche
et d'affichage des résultats
"""
def __init__(self):
self._tk = Tk()
# création des 4 frames
options = {'expand': 1, 'fill': BOTH}
self.add_frame('frm_chemin', FrameChemin?, **options)
self.add_frame('frm_texte', FrameTexte?, **options)
self.add_frame('frm_bouton', FrameButton?, **options)
self.frm_bouton.create_elements(self.stop_recherche,
self.recherche,
self.ferme_fenetre)
self.add_frame('frm_resultat', FrameResultat?, **options)
#, 'relief': RIDGE
self.chercheur = None
# titre fenêtre application
self._tk.wm_title('Recherche')
def mainloop(self):
self._tk.mainloop()
def add_frame(self, name, class_, **pack_options):
instance = class_(self._tk)
setattr(self, name, instance)
instance.pack(**pack_options)
def _retour(self, msg):
""" appelée par le thread """
self.frm_resultat.fenetre_resultats.insert(END, msg)
def _pourcent(self, msg):
""" appelée par le thread """
self._tk.wm_title(msg)
def recherche(self):
""" lance une recherche """
self.stop_recherche()
self.frm_resultat.fenetre_resultats.delete(0, END)
chemin = self.frm_chemin.chemin.get()
texte = self.frm_texte.texte.get()
# lance le thread de recherche
self.chercheur = Recherche(chemin, texte, self._pourcent,
self._retour)
self.chercheur.start()
def stop_recherche(self):
""" stoppe une éventuelle recherche en cours """
if self.chercheur is not None:
self.chercheur.stop()
def ferme_fenetre(self):
""" demande de fermeture, arrêt d'une éventuelle recherche """
self.stop_recherche()
self._tk.destroy()
if __name__ == '__main__':
app = Application()
app.mainloop()