3 # vim: sw=4 ts=4 expandtab ai
9 from os.path import join, abspath, normcase, basename
10 from os.path import isdir, getsize, getatime, getmtime
11 from heapq import nlargest
16 try: import hildon; hildonFound = True
17 except: hildonFound = False
21 # Ищем перевод в /usr/share/locale
22 lang = gettext.translation('findit')
26 # Иначе, ищем в ./ru/LC_MESSAGES/findit.mo
27 langRU = gettext.translation('findit', sys.path[0], languages=['ru'])
30 # Нет и там - используем захардкоженный текст
31 # (закомментировать перед использованием pygettext)
32 def _(text): return text
35 ### Common functions ###########################################################
37 # Функция которая возвращает строку из числа и единиц для столбца "Размер"("Size")
38 def size_convert(size):
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)
44 # Функция поставляющая размер файла и путь к нему
45 def filegetter(startpath, obj):
46 # Список игнорируемых каталогов:
47 ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
48 # Проходим по всем папкам вглубь от заданного пути
49 for dirpath, dirnames, fnames in walk(startpath):
50 # Исключаем каталоги из поиска в соответствии со списком исключений
51 for ign_dir in ignore_dirs[:]:
52 for dirname in dirnames[:]:
53 if ign_dir == normcase(join(abspath(dirpath), dirname)):
54 dirnames.remove(dirname)
55 ignore_dirs.remove(ign_dir)
58 flpath = abspath(join(dirpath, fname))
59 # Выводим текущий опрашиваемый файл в строку статуса
60 obj.currFileLbl.set_text(flpath)
63 # Останавливаем цикл по нажатию кнопки стоп
67 # Проверяем можем ли мы определить размер файла - иначе пропускаем его
68 try: flsize = getsize(flpath)
70 # Возвращаем размер и полный путь файла
74 def toggle_fullscreen(obj):
76 obj.window.unfullscreen()
77 else: obj.window.fullscreen()
78 obj.fullscreen = not obj.fullscreen
80 # Нажатие на кнопку клавиатуры
81 def on_key_press(obj, event):
82 if hildonFound and event.keyval == gtk.keysyms.F6:
83 toggle_fullscreen(obj)
85 ### Properties dialog ##########################################################
87 class PropertiesDialog(gtk.Dialog):
88 def __init__(self, path, size, bytesize):
89 gtk.Dialog.__init__(self)
90 self.set_title( _('File properties') )
91 self.set_transient_for(app)
92 self.set_wmclass('PropertiesDialog', 'FindIT')
93 self.add_buttons(gtk.STOCK_OK, gtk.RESPONSE_OK)
97 access = time.strftime('%x %X', time.localtime(getatime(path)))
98 modified = time.strftime('%x %X', time.localtime(getmtime(path)))
100 table = gtk.Table(2, 2, True)
101 table.set_border_width(10)
102 table.set_col_spacings(10)
103 table.set_row_spacings(10)
105 nameLbl = gtk.Label( _('Name') )
106 nameValueLbl = gtk.Label(name)
108 sizeLbl = gtk.Label( _('Size') )
109 sizeValueLbl = gtk.Label(size + ' (' + `bytesize` + ' b)')
111 accessLbl = gtk.Label( _('Opened') )
112 accessValueLbl = gtk.Label(access)
114 modifiedLbl = gtk.Label( _('Modified') )
115 modifiedValueLbl = gtk.Label(modified)
117 table.attach(nameLbl, 0, 1, 0, 1)
118 table.attach(nameValueLbl, 1, 2, 0, 1)
119 table.attach(sizeLbl, 0, 1, 1, 2)
120 table.attach(sizeValueLbl, 1, 2, 1, 2)
121 table.attach(accessLbl, 0, 1, 2, 3)
122 table.attach(accessValueLbl, 1, 2, 2, 3)
123 table.attach(modifiedLbl, 0, 1, 3, 4)
124 table.attach(modifiedValueLbl, 1, 2, 3, 4)
131 ### Main window ################################################################
133 class MainWindow(gtk.Window):
135 # Окно сообщения заданного типа с заданным текстом
136 def mess_window(self, mestype, content):
137 dialog = gtk.MessageDialog(parent=self, flags=gtk.DIALOG_MODAL,
138 type=mestype, buttons=gtk.BUTTONS_OK,
139 message_format=content)
140 dialog.set_wmclass('ErrorDialog', 'FindIT')
141 dialog.set_title( _('Error!') )
145 # Функция выполняющаяся при нажатии на кнопку "Показать"
146 def start_print(self, widget):
147 self.start_path = self.srch_p_entr.get_text()
148 # Проверяем правильное ли значение введено
149 if isdir(self.start_path):
150 self.butt_start.set_sensitive(False)
151 self.butt_stop.set_sensitive(True)
152 self.propertiesBtn.set_sensitive(False)
153 # Получаем значение количества файлов из SpinButton
154 self.fl_cnt = int( self.file_cnt.get_value() )
156 self.treestore.clear()
157 # Получаем нужное количество самых больших файлов
158 for fsize, fpath in nlargest(self.fl_cnt, filegetter(self.start_path, self)):
159 # Возвращаем значения в treeview в таком порядке - путь,
160 # размер в Мб строкой и размер в байтах
161 # self.treestore.append(None, [fpath.replace(self.start_path,'', 1),
162 # size_convert(fsize), fsize])
164 # Выдает какую-то перманентную ошибку при присвоении значений treestore -
165 # кто увидит скажите - нужна статистика
166 try: self.treestore.append(None, [fpath, size_convert(fsize), fsize])
167 except: 'error', fpath, size_convert(fsize), fsize
168 self.butt_start.set_sensitive(True)
169 self.butt_stop.set_sensitive(False)
170 self.propertiesBtn.set_sensitive(True)
172 # Иначе выводим окошко с ошибкой
173 self.mess_window('error', _('Invalid directory') )
175 # Функция выполняющаяся при нажатии на кнопку "Стоп"
176 def stop_print(self, widget):
179 # Функция выполняющаяся при нажатии на кнопку "Свойства файла"
180 def show_properties_dialog(self, btn):
181 selection = self.treeview.get_selection()
182 (model, it) = selection.get_selected()
184 path = model.get_value(it, 0)
185 size = model.get_value(it, 1)
186 bytesize = model.get_value(it, 2)
188 self.mess_window('error', _('Please select file') )
190 PropertiesDialog(path, size, bytesize)
192 ### Window initialization ##################################################
194 def __init__(self, win_width, win_height, st_path):
196 gtk.Window.__init__(self)
197 self.set_default_size(win_width, win_height)
198 self.set_border_width(4)
199 self.fullscreen = False
200 self.connect('delete_event', gtk.main_quit)
201 self.connect("key-press-event", on_key_press)
202 self.set_wmclass('MainWindow', 'FindIT')
204 ######### Добавляем элементы ################
205 # 1. Строка ввода каталога с которого начинать поиск
206 # переменная в которой храниться стартовый каталог = self.start_path
207 self.srch_p_entr = gtk.Entry()
208 self.start_path = st_path
209 self.srch_p_entr.set_text(self.start_path)
210 # Отключаем автокапитализацию(ввод первой буквы заглавной) на таблетке
212 self.srch_p_entr.set_property("hildon-input-mode", 'full')
213 # Нажатие Enter в поле ввода
214 self.srch_p_entr.connect("activate", self.start_print)
218 # 3. Надпись1 "Количество отображаемых файлов:"
219 label1 = gtk.Label( _('Files quantity') )
221 # 4. Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
222 # данные храняться в переменной self.fl_cnt
225 self.file_cnt = hildon.NumberEditor(1, 99)
226 self.file_cnt.set_value(self.fl_cnt)
228 adj = gtk.Adjustment(self.fl_cnt, 1, 65536, 1, 5, 0)
229 self.file_cnt = gtk.SpinButton(adj, 0, 0)
231 # 5.1 Кнопка "Показать"
232 self.butt_start = gtk.Button( _('Go') )
233 self.butt_start.connect('clicked', self.start_print)
235 # 5.2 Кнопка "Остановить"
236 self.butt_stop = gtk.Button( _('Stop') )
237 self.butt_stop.set_sensitive(False)
238 self.butt_stop.connect('clicked', self.stop_print)
241 # 5.3 Кнопка "Свойства файла"
242 self.propertiesBtn = gtk.Button( _('File properties') )
243 self.propertiesBtn.connect('clicked', self.show_properties_dialog)
244 self.propertiesBtn.set_sensitive(False)
249 scrollwind = gtk.ScrolledWindow()
250 scrollwind.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
252 # Определяем переменную в которой будет храниться выводимый список
253 self.treestore = gtk.TreeStore(str, str, int)
254 self.treeview = gtk.TreeView(self.treestore)
255 # На таблетке не отображаються заголовки столбцов по умолчанию -
256 # след строка заставляет их отображаться принудительно
257 self.treeview.set_headers_visible(1)
259 self.treestore.append(None, ['','', 0])
261 # Создаем и настраиваем колонку с размером файла
262 size_col = gtk.TreeViewColumn( _('Size') )
263 cell = gtk.CellRendererText()
264 cell.set_property('width', 90)
265 size_col.pack_start(cell, True)
266 size_col.add_attribute(cell, 'text', 1)
267 self.treeview.append_column(size_col)
268 # Создаем и настраиваем колонку с именем файла
269 path_col = gtk.TreeViewColumn( _('Path') )
270 cell2 = gtk.CellRendererText()
271 path_col.pack_start(cell2, True)
272 path_col.add_attribute(cell2, 'text', 0)
273 self.treeview.append_column(path_col)
275 # Добавляем сортировку для колонок
276 self.treeview.set_search_column(1)
277 path_col.set_sort_column_id(0)
278 size_col.set_sort_column_id(2)
280 # 6.2 Надпись "Найти"
282 # 6.3 Строка выводящая текущий осматриваемый файл
283 self.currFileLbl = gtk.Label()
284 self.currFileLbl.set_alignment(0, 0.5)
285 self.currFileLbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
287 ######### Упаковываем элементы ################
288 # Создаем основной вертикальный контейнер
289 main_Vbox = gtk.VBox(False, 4)
291 # Создаем вспомогательный горизонтальный контейнер для Надписи1,
292 # окошка ввода количества файлов и кнопки "Показать"
293 hbox1 = gtk.HBox(False, 5)
294 # Добавляем вышеперечисленные элементы во вспомогат. контейнер
295 hbox1.pack_start(label1, False, False, 5)
296 hbox1.pack_start(self.file_cnt, False, False, 0)
297 hbox1.pack_start(self.butt_start, True, True, 0)
298 hbox1.pack_start(self.butt_stop, True, True, 0)
299 hbox1.pack_start(self.propertiesBtn, True, True, 0)
301 # Добавляем элементы в основной контейнер
302 main_Vbox.pack_start(self.srch_p_entr, False, False, 0)
303 main_Vbox.pack_start(hbox1, False, False, 0)
304 scrollwind.add(self.treeview)
305 main_Vbox.pack_start(scrollwind, True, True, 0)
306 main_Vbox.pack_start(self.currFileLbl, False, False, 0)
316 ### Main call ##################################################################
318 if __name__ == '__main__':
319 # gobject.set_application_name( _('FindIT') )
320 app = MainWindow(575, 345, '.')