3 # vim: sw=4 ts=4 expandtab ai
9 from os.path import getsize, join, isdir, abspath, normcase
10 from heapq import nlargest
14 try: import hildon; hildonFound = True
15 except: hildonFound = False
18 # Подразумевается, что ru/LC_MESSAGES/program.mo находится в текущем каталоге (sys.path[0])
19 # Для стандартного /usr/share/locale писать gettext.translation('findit')
20 langRU = gettext.translation('findit', sys.path[0], languages=['ru'])
23 def _(text): return text
26 ### Common functions ###########################################################
28 # Функция которая возвращает строку из числа и единиц для столбца "Размер"("Size")
29 def size_convert(size):
30 for i, unit in enumerate(['%d b', '%.1f Kb', '%.2f Mb', '%.3f Gb', '%.4f Tb']):
31 if size < 1024**(i+1):
32 return unit % (size/1024.**i)
35 # Функция поставляющая размер файла и путь к нему
36 def filegetter(startpath, obj):
37 # Список игнорируемых каталогов:
38 ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
39 # Проходим по всем папкам вглубь от заданного пути
40 for dirpath, dirnames, fnames in walk(startpath):
41 # Исключаем каталоги из поиска в соответствии со списком исключений
42 for ign_dir in ignore_dirs[:]:
43 for dirname in dirnames[:]:
44 if ign_dir == normcase(join(abspath(dirpath), dirname)):
45 dirnames.remove(dirname)
46 ignore_dirs.remove(ign_dir)
49 flpath = join(dirpath, fname)
50 # Выводим текущий опрашиваемый файл в строку статуса
51 obj.currFileLbl.set_text(abspath(flpath))
54 # Останавливаем цикл по нажатию кнопки стоп
58 # Проверяем можем ли мы определить размер файла - иначе пропускаем его
59 try: flsize = getsize(flpath)
61 # Возвращаем размер и полный путь файла
65 def toggle_fullscreen(obj):
67 obj.window.unfullscreen()
69 obj.window.fullscreen()
70 obj.fullscreen = not obj.fullscreen
72 # Нажатие на кнопку клавиатуры
73 def on_key_press(obj, event):
74 if hildonFound and event.keyval == gtk.keysyms.F6:
75 toggle_fullscreen(obj)
77 ### Main window ################################################################
79 class MainWindow(gtk.Window):
81 # Окно сообщения заданного типа с заданным текстом
82 def mess_window(self, mestype, content):
83 dialog = gtk.MessageDialog(parent=self, flags=gtk.DIALOG_MODAL, \
84 type=mestype, buttons=gtk.BUTTONS_OK, message_format=content)
88 # Функция выполняющаяся при нажатии на кнопку "Показать"
89 def start_print(self, widget):
90 self.butt_start.set_sensitive(False)
91 self.butt_stop.set_sensitive(True)
92 self.fl_cnt = int( self.file_cnt.get_value() )
93 self.start_path = self.srch_p_entr.get_text()
95 self.treestore.clear()
96 # Проверяем правильное ли значение введено
97 if isdir(self.start_path):
98 # Получаем нужное количество самых больших файлов
99 for fsize, fpath in nlargest(self.fl_cnt, filegetter(self.start_path, self)):
100 # Возвращаем значения в treeview в таком порядке - путь,
101 # размер в Мб строкой и размер в байтах
102 # self.treestore.append(None, [fpath.replace(self.start_path,'', 1),\
103 # size_convert(fsize), fsize])
105 # Выдает какую-то перманентную ошибку при присвоении значений treestore -
106 # кто увидит скажите - нужна статистика
107 try: self.treestore.append(None, [fpath, size_convert(fsize), fsize])
108 except: 'error', fpath, size_convert(fsize), fsize
109 self.butt_start.set_sensitive(True)
110 self.butt_stop.set_sensitive(False)
112 # Иначе выводим окошко с ошибкой
113 self.mess_window(gtk.MESSAGE_ERROR, _('Invalid directory') )
115 def stop_print(self, widget):
118 ### Window initialization ##################################################
120 def __init__(self, win_width, win_height, st_path):
122 gtk.Window.__init__(self)
123 self.set_default_size(win_width, win_height)
124 self.set_border_width(4)
125 self.fullscreen = False
126 self.connect('delete_event', gtk.main_quit)
127 self.connect("key-press-event", on_key_press)
129 ######### Добавляем элементы ################
130 # 1. Строка ввода каталога с которого начинать поиск
131 # переменная в которой храниться стартовый каталог = self.start_path
132 self.srch_p_entr = gtk.Entry()
133 self.start_path = st_path
134 self.srch_p_entr.set_text(self.start_path)
135 # Отключаем автокапитализацию(ввод первой буквы заглавной) на таблетке
137 self.srch_p_entr.set_property("hildon-input-mode", 'full')
138 # Нажатие Enter в поле ввода
139 self.srch_p_entr.connect("activate", self.start_print)
143 # 3. Надпись1 "Количество отображаемых файлов:"
144 label1 = gtk.Label( _('Files quantity') )
146 # 4. Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
147 # данные храняться в переменной self.fl_cnt
150 self.file_cnt = hildon.NumberEditor(1, 65536)
151 self.file_cnt.set_value(self.fl_cnt)
153 adj = gtk.Adjustment(self.fl_cnt, 1, 65536, 1, 5, 0)
154 self.file_cnt = gtk.SpinButton(adj, 0, 0)
156 # 5.1 Кнопка "Показать"
157 self.butt_start = gtk.Button( _('Go') )
158 self.butt_start.connect('clicked', self.start_print)
160 # 5.2 Кнопка "Остановить"
161 self.butt_stop = gtk.Button( _('Stop') )
162 self.butt_stop.set_sensitive(False)
163 self.butt_stop.connect('clicked', self.stop_print)
169 scrollwind = gtk.ScrolledWindow()
170 scrollwind.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
172 # Определяем переменную в которой будет храниться выводимый список
173 self.treestore = gtk.TreeStore(str, str, int)
174 treeview = gtk.TreeView(self.treestore)
175 # На таблетке не отображаються заголовки столбцов по умолчанию -
176 # след строка заставляет их отображаться принудительно
177 treeview.set_headers_visible(1)
179 self.treestore.append(None, ['','', 0])
181 # Создаем и настраиваем колонку с размером файла
182 size_col = gtk.TreeViewColumn( _('Size') )
183 cell = gtk.CellRendererText()
184 cell.set_property('width', 90)
185 size_col.pack_start(cell, True)
186 size_col.add_attribute(cell, 'text', 1)
187 treeview.append_column(size_col)
188 # Создаем и настраиваем колонку с именем файла
189 path_col = gtk.TreeViewColumn( _('Path') )
190 cell2 = gtk.CellRendererText()
191 path_col.pack_start(cell2, True)
192 path_col.add_attribute(cell2, 'text', 0)
193 treeview.append_column(path_col)
195 # Добавляем сортировку для колонок
196 treeview.set_search_column(1)
197 path_col.set_sort_column_id(0)
198 size_col.set_sort_column_id(2)
200 # 6.2 Надпись "Найти"
202 # 6.3 Строка выводящая текущий осматриваемый файл
203 self.currFileLbl = gtk.Label()
204 self.currFileLbl.set_alignment(0, 0.5)
205 self.currFileLbl.set_text('---')
206 self.currFileLbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
208 ######### Упаковываем элементы ################
209 # Создаем основной вертикальный контейнер
210 main_Vbox = gtk.VBox(False, 4)
212 # Создаем вспомогательный горизонтальный контейнер для Надписи1,
213 # окошка ввода количества файлов и кнопки "Показать"
214 hbox1 = gtk.HBox(False, 5)
215 # Добавляем вышеперечисленные элементы во вспомогат. контейнер
216 hbox1.pack_start(label1, False, False, 5)
217 hbox1.pack_start(self.file_cnt, False, False, 0)
218 hbox1.pack_start(self.butt_start, True, True, 0)
219 hbox1.pack_start(self.butt_stop, True, True, 0)
221 # Добавляем элементы в основной контейнер
222 main_Vbox.pack_start(self.srch_p_entr, False, False, 0)
223 main_Vbox.pack_start(hbox1, False, False, 0)
224 scrollwind.add(treeview)
225 main_Vbox.pack_start(scrollwind, True, True, 0)
226 main_Vbox.pack_start(self.currFileLbl, False, False, 0)
236 ### Main call ##################################################################
238 if __name__ == '__main__':
239 # gobject.set_application_name( _('FindIT') )
240 MainWindow(575, 345, '/').run()