250d5322ebe9a1b0e14e7240dd3232954063082f
[findit] / src / mvc / controllers / filesearch.py
1 #!/usr/bin/env python
2 # -*-coding: utf-8 -*-
3 # vim: sw=4 ts=4 expandtab ai
4 # pylint: disable-msg=C0301
5
6 from gtkmvc import Controller
7 import gtk
8
9 from os import walk
10 from os.path import join, abspath, normcase, getsize
11 from heapq import nlargest
12
13 #from filesearch import FilesearchCtrl
14 from views.filesearch import FilesearchView
15
16
17 class FilesearchCtrl(Controller):
18     """Controller of the files search plugin"""
19
20     def __init__(self, model):
21         Controller.__init__(self, model)
22
23     def register_view(self, view):
24         Controller.register_view(self, view)
25
26         # connects the signals:
27         self.view['start_btn'].connect('released', self.start_btn_released_cb)
28         self.view['stop_btn'].connect('clicked', self.on_stop_btn_clicked)
29         self.view['qty_spin'].connect("value_changed", self.on_qty_spin_value_changed)
30
31         # sets initial values for the view
32         self.view.set_quantity_value(self.model.quantity)
33         self.view.set_start_path_value(self.model.start_path)
34
35     # -----------------------------------------------------
36     #                  user callbacks
37     # -----------------------------------------------------
38
39     def filegetter(self, startdir):  #, obj):
40         """Generator of file sizes and paths based on os.walk."""
41         # Список игнорируемых каталогов:
42         ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
43         # Проходим по всем папкам вглубь от заданного пути
44         for dirpath, dirnames, fnames in walk(startdir):
45         # Исключаем каталоги из поиска в соответствии со списком исключений
46             for ign_dir in ignore_dirs[:]:
47                 for dirname in dirnames[:]:
48                     if ign_dir == normcase(join(abspath(dirpath), dirname)):
49                         dirnames.remove(dirname)
50                         ignore_dirs.remove(ign_dir)
51     
52             for fname in fnames:
53                 flpath = abspath(join(dirpath, fname))
54                 # Выводим текущий опрашиваемый файл в строку статуса
55                 self.view['currfile_lbl'].set_text(flpath)
56                 # обновляем окно
57                 gtk.main_iteration()
58                 # Останавливаем цикл по нажатию кнопки стоп
59                 if self.model.stopit:
60                     self.model.stopit = False
61                     raise StopIteration
62                 # Проверяем можем ли мы определить размер файла - иначе пропускаем его
63                 try:
64                     # Возвращаем размер и полный путь файла
65                     yield getsize(flpath), flpath
66                 except OSError:
67                     continue
68
69     def size_convert(self, size):
70         """Return string with file size in b or Kb or Mb or Gb or Tb."""
71
72         for i, unit in enumerate(['%d b', '%.1f Kb', '%.2f Mb', '%.3f Gb', '%.4f Tb']):
73             if size < 1024**(i+1):
74                 return unit % (size/1024.**i)
75         return '>1024 Tb'
76
77     # -----------------------------------------------------
78     #                    gtk signals
79     # -----------------------------------------------------
80
81     def on_qty_spin_value_changed(self, sb):
82         # Получаем значение количества файлов из SpinButton
83         self.model.quantity = sb.get_value_as_int()
84
85     def start_btn_released_cb(self, btn):
86         """Start file search. Button "Go" activate callback."""         
87
88         # Получаем значение начального пути из Entry
89         start_path = self.view['path_entry'].get_text()
90
91         self.view['start_btn'].set_sensitive(False)
92         self.view['stop_btn'].set_sensitive(True)
93
94         # Очищаем список
95         self.view['liststore'].clear()
96
97         # Выравниваем размер колонок
98         self.view['treeview'].columns_autosize()
99
100         # Получаем нужное количество самых больших файлов
101         #for fsize, fpath in nlargest(self.model.quantity, self.filegetter(self.model.start_path)):
102         for fsize, fpath in nlargest(self.model.quantity, self.filegetter(start_path)):
103             # Заполняем treemodel: путь, размер в Мб строкой, размер в байтах
104 #             try:
105                 self.view['liststore'].append([fpath, self.size_convert(fsize), fsize])
106 #             except:
107 #                 print type(fpath), type(self.size_convert(fsize)), type(fsize)
108
109         self.view['start_btn'].set_sensitive(True)
110         self.view['stop_btn'].set_sensitive(False)
111         self.view['path_entry'].grab_focus()
112
113     def on_stop_btn_clicked(self, btn):
114         """Stop search. "Stop" button clicked callback."""
115         print 'Stop clicked'
116         self.model.stopit = True
117
118     # -----------------------------------------------------
119     #                observable properties
120     # -----------------------------------------------------
121
122     def property_quantity_value_change(self, model, old, new):
123         pass
124         #self.view.set_quantity_value(new)
125
126     def property_start_path_value_change(self, model, old, new):
127         print model, old, new
128         self.view.set_start_path_value(new)
129
130     def property_stopit_value_change(self, model, old, new):
131         self.view.set_stopit_value(new)