add simple calc full directory size
[findit] / src / filesearch.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 from misc import size_hum_read
13
14 class Search_File_Control(object):
15     
16     def __init__(self, config, show_func):
17         win_width = config.get('window_width')
18         win_height = config.get('window_height')
19         count = config.get('default_count')
20         start_path = config.get('default_start_dir')
21         ignore_dirs = config.get('ignore_dir_list')
22         self.srch_abs = Search_File_Abstraction(ignore_dirs)
23         self.srch_present = Search_File_Presentation(win_width, win_height, start_path, count, self.start_search)
24         self.result_out = show_func
25
26     def run(self):
27         self.srch_present.run()
28
29     def start_search(self, get_data, get_stopit, label, kill_func):
30         filelist = []
31         start_path, count = get_data()
32         for fsize, fpath in nlargest(count, \
33                 self.srch_abs.filegetter(start_path, get_stopit, label) ):
34             filelist.append([fpath, size_hum_read(fsize), int(fsize)])
35         print size_hum_read(self.srch_abs.full())
36         if not get_stopit():
37             kill_func()
38             self.result_out.show(filelist)
39             self.result_out.run()
40
41
42 class Search_File_Abstraction(object):
43     
44     def __init__(self, ignore_dirs):
45         self.ignore_dirs = ignore_dirs
46
47     def filegetter(self, startdir, get_stopit, label):
48         """Generator of file sizes and paths based on os.walk."""
49         # Проходим по всем папкам вглубь от заданного пути
50         self.full_dir_size = 0
51         for dirpath, dirnames, fnames in walk(startdir):
52         # Исключаем каталоги из поиска в соответствии со списком исключений
53             ignore_dirs = self.ignore_dirs
54             for ign_dir in ignore_dirs[:]:
55                 for dirname in dirnames[:]:
56                     if ign_dir == normcase(join(abspath(dirpath), dirname)):
57                         dirnames.remove(dirname)
58                         ignore_dirs.remove(ign_dir)
59
60             for fname in fnames:
61                 flpath = abspath(join(dirpath, fname))
62                 # Выводим текущий опрашиваемый файл в строку статуса
63                 label.set_text(flpath)
64                 # обновляем окно
65                 gtk.main_iteration()
66                 # Останавливаем цикл по нажатию кнопки стоп
67                 stopit = get_stopit()
68                 if stopit:
69                     stopit = False
70                     raise StopIteration
71                 # Проверяем можем ли мы определить размер файла - иначе пропускаем его
72                 try:
73                     # Возвращаем размер и полный путь файла
74                     self.full_dir_size = getsize(flpath) + self.full_dir_size
75                     yield getsize(flpath), flpath
76                 except OSError:
77                     continue
78
79     def full(self):
80         return self.full_dir_size
81   
82 class Search_File_Presentation(gtk.Window):
83     
84     #def __init__(self, win_width, win_height, count, st_func, show_func):
85     def __init__(self, win_width, win_height, start_path, count, st_func):
86         """Create MainWindow."""
87         # Создаем новое окно
88         gtk.Window.__init__(self)
89         self.set_default_size(win_width, win_height)
90         self.set_border_width(4)
91         self.connect('delete_event', gtk.main_quit)
92         
93         # Строка ввода каталога
94         self.srch_p_entr = gtk.Entry()
95         self.srch_p_entr.set_text(start_path)
96
97         label1 = gtk.Label('Files quantity')
98         # Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
99         adj = gtk.Adjustment(count, 1, 65536, 1, 5, 0)
100         self.file_cnt = gtk.SpinButton(adj, 0, 0)   
101
102         # Строка вывода текущего осматриваемого файла
103         self.currfilelbl = gtk.Label('---')
104         self.currfilelbl.set_alignment(0, 0.5)
105         self.currfilelbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
106         self.currfilelbl.set_padding(2, 2)
107         currfilefrm = gtk.Frame()
108         currfilefrm.add(self.currfilelbl)
109
110         # Кнопка "Показать"
111         self.butt_start = gtk.Button('Go >')
112         self.butt_start.connect('released', self.start_srch, st_func)
113
114         # Кнопка "Остановить"
115         self.butt_stop = gtk.Button('Stop')
116         self.butt_stop.set_sensitive(False)
117         self.stopit = False
118         self.butt_stop.connect('clicked', self.stop_srch)
119         
120         self.butt_prev = gtk.Button('< Previous')
121         
122         main_vbox = gtk.VBox(False, 0)
123         hbox1 = gtk.HBox(False, 0)
124         hbox1.pack_start(label1, True, True, 0)
125         hbox1.pack_start(self.file_cnt, False, False, 0)
126         
127         hbox2 = gtk.HBox(False, 0)
128         hbox2.pack_start(currfilefrm, True, True, 0)
129         hbox2.pack_end(self.butt_stop, False, False, 0)
130
131         hbox3 = gtk.HBox(False, 0)
132         hbox3.pack_start(self.butt_prev, False, False, 0)
133         hbox3.pack_start(self.butt_start, False, False, 0)
134         
135         main_vbox.pack_start(self.srch_p_entr, False, False, 0)
136         main_vbox.pack_start(hbox1, False, False, 0)
137         main_vbox.pack_start(hbox2, False, False, 0)
138         main_vbox.pack_start(hbox3, False, False, 0)
139
140         self.add(main_vbox)
141
142     def start_srch(self, widget, start_func):
143         self.stopit = False
144         self.butt_stop.set_sensitive(True)
145         self.butt_start.set_sensitive(False)
146         start_func(self.get_data, self.get_stopit, self.currfilelbl, self.kill_wind)
147
148     def kill_wind(self):
149         self.destroy()
150         gtk.main_quit()
151         
152     def stop_srch(self, widget):
153         self.stopit = True
154         self.butt_stop.set_sensitive(False)
155         self.butt_start.set_sensitive(True)
156
157     def get_stopit(self):
158         return self.stopit
159
160     def run(self):
161         self.show_all()
162         gtk.main()
163
164     def get_data(self):
165         return self.srch_p_entr.get_text(), int( self.file_cnt.get_value() )