08f2da072531ba3c8ae1b203d7ff739431bd7c7c
[findit] / src / searchfile.py
1 #!/usr/bin/env python
2 # -*-coding: utf-8 -*-
3 # vim: sw=4 ts=4 expandtab ai
4
5 import gtk
6 import pango
7 from os import walk
8 from os.path import join, abspath, normcase, basename, \
9                             isdir, getsize
10 from heapq import nlargest
11
12 class Search_File_Control(object):
13     
14     def __init__(self, start_dir, count, ignore_dirs, show_func):
15         self.filelist = []
16         self.fl_cnt = count
17         self.srch_abs = Search_File_Abstraction(start_dir, ignore_dirs)
18         self.srch_present = Search_File_Presentation(self.start_search, show_func)
19
20     def get_ui(self):
21         return self.srch_present.get_ui()
22
23     def start_search(self, stopit, label, show_func):
24         #count, start_path = self.srch_present() 
25         for fsize, fpath in nlargest(self.fl_cnt, \
26                 self.srch_abs.filegetter(stopit, label) ):
27             self.filelist.append([fpath, self.srch_abs.size_convert(fsize), fsize])
28         show_func(self.filelist)
29
30
31 class Search_File_Abstraction(object):
32     
33     def __init__(self, startdir, ignore_dirs):
34         self.startdir = startdir
35         self.ignore_dirs = ignore_dirs
36         
37     def size_convert(self, size):
38         """Return string with file size in b or Kb or Mb or Gb or Tb."""
39         for i, unit in enumerate(['%d b', '%.1f Kb', '%.2f Mb', '%.3f Gb', '%.4f Tb']):
40             if size < 1024**(i+1):
41                 return unit % (size/1024.**i)
42         return '>1024 Tb'
43
44     def filegetter(self, stopit, label):
45         """Generator of file sizes and paths based on os.walk."""
46         # Проходим по всем папкам вглубь от заданного пути
47         for dirpath, dirnames, fnames in walk(self.startdir):
48         # Исключаем каталоги из поиска в соответствии со списком исключений
49             for ign_dir in self.ignore_dirs[:]:
50                 for dirname in dirnames[:]:
51                     if ign_dir == normcase(join(abspath(dirpath), dirname)):
52                         dirnames.remove(dirname)
53                         ignore_dirs.remove(ign_dir)
54
55             for fname in fnames:
56                 flpath = abspath(join(dirpath, fname))
57                 # Выводим текущий опрашиваемый файл в строку статуса
58                 label.set_text(flpath)
59                 # обновляем окно
60                 gtk.main_iteration()
61                 # Останавливаем цикл по нажатию кнопки стоп
62                 if stopit:
63                     stopit = False
64                     raise StopIteration
65                 # Проверяем можем ли мы определить размер файла - иначе пропускаем его
66                 try:
67                     # Возвращаем размер и полный путь файла
68                     yield getsize(flpath), flpath
69                 except OSError:
70                     continue
71   
72 class Search_File_Presentation(object):
73     
74     def __init__(self, st_func, show_func):
75
76         # Строка вывода текущего осматриваемого файла
77         self.currfilelbl = gtk.Label('---')
78         self.currfilelbl.set_alignment(0, 0.5)
79         self.currfilelbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
80         self.currfilelbl.set_padding(2, 2)
81         currfilefrm = gtk.Frame()
82         currfilefrm.add(self.currfilelbl)
83
84         # Кнопка "Показать"
85         self.butt_start = gtk.Button('Go')
86
87         # Кнопка "Остановить"
88         self.butt_stop = gtk.Button('Stop')
89         self.butt_stop.set_sensitive(False)
90         self.stopit = False
91         self.butt_stop.connect('clicked', self.stop_srch)
92         self.butt_start.connect('released', self.start_srch, st_func, show_func)
93         
94
95         self.search_hbox = gtk.HBox(False, 10)
96         self.search_hbox.pack_start(currfilefrm, False, False, 0)
97         self.search_hbox.pack_end(self.butt_start, False, False, 0)
98         self.search_hbox.pack_end(self.butt_stop, False, False, 0)
99
100     def get_ui(self):
101         return self.search_hbox
102
103     def start_srch(self, widget, start_func, show_func):
104         self.butt_stop.set_sensitive(True)
105         self.butt_start.set_sensitive(False)
106         start_func(self.stopit, self.currfilelbl, show_func)
107         self.butt_stop.set_sensitive(False)
108         self.butt_start.set_sensitive(True)
109
110     def stop_srch(self, widget):
111         self.stopit = True
112         self.butt_stop.set_sensitive(False)
113         self.butt_start.set_sensitive(True)