3 # vim: sw=4 ts=4 expandtab ai
4 # pylint: disable-msg=C0301
10 from os.path import join, abspath, normcase, basename, \
11 isdir, getsize, getatime, getmtime, expanduser
12 from heapq import nlargest
15 from sys import platform
24 # Подразумевается, что ru/LC_MESSAGES/program.mo находится в текущем каталоге (sys.path[0])
25 # Для стандартного /usr/share/locale писать gettext.translation('findit')
26 #langRU = gettext.translation('findit', sys.path[0], languages=['ru'])
27 langRU = gettext.translation('findit')
30 # Закомментировать перед использованием pygettext
35 ### Common functions ###########################################################
37 # Функция которая возвращает строку из числа и единиц для столбца "Размер"("Size")
38 def size_convert(size):
39 """This function return string with file size in
40 b or Kb or Mb or Gb or Tb
42 for i, unit in enumerate(['%d b', '%.1f Kb', '%.2f Mb', '%.3f Gb', '%.4f Tb']):
43 if size < 1024**(i+1):
44 return unit % (size/1024.**i)
47 # Функция поставляющая размер файла и путь к нему
48 def filegetter(startdir, obj):
49 """This function-generator return size
50 and path for all files in start directory
52 # Список игнорируемых каталогов:
53 ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
54 # Проходим по всем папкам вглубь от заданного пути
55 for dirpath, dirnames, fnames in walk(startdir):
56 # Исключаем каталоги из поиска в соответствии со списком исключений
57 for ign_dir in ignore_dirs[:]:
58 for dirname in dirnames[:]:
59 if ign_dir == normcase(join(abspath(dirpath), dirname)):
60 dirnames.remove(dirname)
61 ignore_dirs.remove(ign_dir)
64 flpath = abspath(join(dirpath, fname))
65 # Выводим текущий опрашиваемый файл в строку статуса
66 obj.currFileLbl.set_text(flpath)
69 # Останавливаем цикл по нажатию кнопки стоп
73 # Проверяем можем ли мы определить размер файла - иначе пропускаем его
75 flsize = getsize(flpath)
76 # Возвращаем размер и полный путь файла
82 def toggle_fullscreen(obj):
83 """This function switch and unswitch to fullscreen"""
85 obj.window.unfullscreen()
87 obj.window.fullscreen()
88 obj.fullscreen = not obj.fullscreen
90 # Нажатие на кнопку клавиатуры
91 def on_key_press(obj, event):
92 """This function start then FullScreen button on N8xx pressed"""
93 if hildonFound and event.keyval == gtk.keysyms.F6:
94 toggle_fullscreen(obj)
96 ### Properties dialog ##########################################################
98 class PropertiesDialog(gtk.Dialog):
99 """This class describe property window"""
100 def __init__(self, path, size, bytesize):
101 """Creating new object of PropertiesDialog class"""
102 gtk.Dialog.__init__(self)
103 self.set_title( _('File properties') )
104 self.set_transient_for(app)
105 self.set_wmclass('PropertiesDialog', 'FindIT')
106 self.add_buttons(gtk.STOCK_OK, gtk.RESPONSE_OK)
107 self.set_resizable(False)
109 # Достаем свойства выбранного файла
110 name = basename(path)
111 access = time.strftime('%x %X', time.localtime(getatime(path)))
112 modified = time.strftime('%x %X', time.localtime(getmtime(path)))
116 table.set_border_width(10)
117 table.set_col_spacings(10)
118 table.set_row_spacings(10)
120 # Надписи (подпись: значение)
121 nameLbl = gtk.Label( _('Name') )
122 nameValueLbl = gtk.Label(name)
124 sizeLbl = gtk.Label( _('Size') )
125 sizeValueLbl = gtk.Label(size + ' (' + `bytesize` + ' b)')
127 accessLbl = gtk.Label( _('Opened') )
128 accessValueLbl = gtk.Label(access)
130 modifiedLbl = gtk.Label( _('Modified') )
131 modifiedValueLbl = gtk.Label(modified)
134 lbls = [(nameLbl, nameValueLbl), (sizeLbl, sizeValueLbl),
135 (accessLbl, accessValueLbl), (modifiedLbl, modifiedValueLbl)]
137 # Упаковка надписей в таблицу и выравнивание
138 for i, lbl in enumerate(lbls):
140 table.attach(name, 0, 1, i, i+1)
141 table.attach(value, 1, 2, i, i+1)
142 name.set_alignment(1, 0.5)
143 value.set_alignment(0, 0.5)
145 # Упаковка таблицы в vbox диалога
151 ### Main window ################################################################
153 class MainWindow(gtk.Window):
154 """This class describe main window of FindIT"""
156 # Окно сообщения заданного типа с заданным текстом
157 def mess_window(self, mestype, content):
158 """This function show popup message window"""
159 dialog = gtk.MessageDialog(parent=self, flags=gtk.DIALOG_MODAL,
160 type=mestype, buttons=gtk.BUTTONS_OK,
161 message_format=content)
162 dialog.set_wmclass('ErrorDialog', 'FindIT')
163 dialog.set_title( _('Error!') )
167 # Функция выполняющаяся при нажатии на кнопку "Показать"
168 def start_print(self, widget):
169 """This function start then "Go" button pressed.
170 Starting file search.
172 self.start_path = self.srch_p_entr.get_text()
173 # Проверяем правильное ли значение введено
174 if isdir(self.start_path):
175 self.butt_start.set_sensitive(False)
176 self.butt_stop.set_sensitive(True)
177 self.propertiesBtn.set_sensitive(False)
178 # Получаем значение количества файлов из SpinButton
179 self.fl_cnt = int( self.file_cnt.get_value() )
181 self.treestore.clear()
182 # Получаем нужное количество самых больших файлов
183 for fsize, fpath in nlargest(self.fl_cnt, filegetter(self.start_path, self)):
184 # Возвращаем значения в treeview в таком порядке - путь,
185 # размер в Мб строкой и размер в байтах
186 # self.treestore.append(None, [fpath.replace(self.start_path,'', 1),
187 # size_convert(fsize), fsize])
189 # Выдает какую-то перманентную ошибку при присвоении значений treestore -
190 # кто увидит скажите - нужна статистика
192 self.treestore.append(None, [fpath, size_convert(fsize), fsize])
194 # print 'error', fpath, size_convert(fsize), fsize
195 self.mess_window('error','Error in %s' % fpath)
196 self.butt_start.set_sensitive(True)
197 self.butt_stop.set_sensitive(False)
198 self.propertiesBtn.set_sensitive(True)
199 self.srch_p_entr.grab_focus()
201 # Иначе выводим окошко с ошибкой
202 self.mess_window('error', _('Invalid directory') )
204 # Функция выполняющаяся при нажатии на кнопку "Стоп"
205 def stop_print(self, widget):
206 """This function start then "Stop" button pressed.
211 # Функция выполняющаяся при нажатии на кнопку "Свойства файла"
212 def show_properties_dialog(self, *args):
213 """This function show property window"""
214 selection = self.treeview.get_selection()
215 (model, it) = selection.get_selected()
217 path = model.get_value(it, 0)
218 size = model.get_value(it, 1)
219 bytesize = model.get_value(it, 2)
220 except (TypeError, ValueError):
221 self.mess_window('error', _('Please select file') )
223 PropertiesDialog(path, size, bytesize)
225 ### Window initialization ##################################################
227 def __init__(self, win_width, win_height, st_path):
228 """Creating new object of MainWindow class"""
230 gtk.Window.__init__(self)
231 self.set_default_size(win_width, win_height)
232 self.set_border_width(4)
233 self.fullscreen = False
234 self.connect('delete_event', gtk.main_quit)
235 self.connect("key-press-event", on_key_press)
236 self.set_wmclass('MainWindow', 'FindIT')
238 ######### Добавляем элементы ################
239 # 1. Строка ввода каталога с которого начинать поиск
240 # переменная в которой храниться стартовый каталог = self.start_path
241 self.srch_p_entr = gtk.Entry()
242 self.start_path = st_path
243 self.srch_p_entr.set_text(self.start_path)
244 # Отключаем автокапитализацию(ввод первой буквы заглавной) на таблетке
246 self.srch_p_entr.set_property("hildon-input-mode", 'full')
247 # Нажатие Enter в поле ввода
248 self.srch_p_entr.connect("activate", self.start_print)
252 # 3. Надпись1 "Количество отображаемых файлов:"
253 label1 = gtk.Label( _('Files quantity') )
255 # 4. Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
256 # данные храняться в переменной self.fl_cnt
259 self.file_cnt = hildon.NumberEditor(1, 99)
260 self.file_cnt.set_value(self.fl_cnt)
262 adj = gtk.Adjustment(self.fl_cnt, 1, 65536, 1, 5, 0)
263 self.file_cnt = gtk.SpinButton(adj, 0, 0)
265 # 5.1 Кнопка "Показать"
266 self.butt_start = gtk.Button( _('Go') )
267 self.butt_start.connect('released', self.start_print)
269 # 5.2 Кнопка "Остановить"
270 self.butt_stop = gtk.Button( _('Stop') )
271 self.butt_stop.set_sensitive(False)
272 self.butt_stop.connect('clicked', self.stop_print)
275 # 5.3 Кнопка "Свойства файла"
276 self.propertiesBtn = gtk.Button( _('File properties') )
277 self.propertiesBtn.connect('clicked', self.show_properties_dialog)
278 self.propertiesBtn.set_sensitive(False)
283 scrollwind = gtk.ScrolledWindow()
284 scrollwind.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
286 # Определяем переменную в которой будет храниться выводимый список
287 self.treestore = gtk.TreeStore(str, str, int)
288 self.treeview = gtk.TreeView(self.treestore)
289 # На таблетке не отображаються заголовки столбцов по умолчанию -
290 # след строка заставляет их отображаться принудительно
291 self.treeview.set_headers_visible(1)
292 self.treeview.connect('row-activated', self.show_properties_dialog)
294 self.treestore.append(None, ['', '', 0])
296 # Создаем и настраиваем колонку с размером файла
297 size_col = gtk.TreeViewColumn( _('Size') )
298 cell = gtk.CellRendererText()
299 cell.set_property('width', 90)
300 size_col.pack_start(cell, True)
301 size_col.add_attribute(cell, 'text', 1)
302 self.treeview.append_column(size_col)
303 # Создаем и настраиваем колонку с именем файла
304 path_col = gtk.TreeViewColumn( _('Path') )
305 cell2 = gtk.CellRendererText()
306 path_col.pack_start(cell2, True)
307 path_col.add_attribute(cell2, 'text', 0)
308 self.treeview.append_column(path_col)
310 # Добавляем сортировку для колонок
311 self.treeview.set_search_column(1)
312 path_col.set_sort_column_id(0)
313 size_col.set_sort_column_id(2)
315 # 6.2 Надпись "Найти"
317 # 6.3 Строка выводящая текущий осматриваемый файл
318 self.currFileLbl = gtk.Label()
319 self.currFileLbl.set_alignment(0, 0.5)
320 self.currFileLbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
321 self.currFileLbl.set_padding(2, 2)
322 currFileFrm = gtk.Frame()
323 currFileFrm.add(self.currFileLbl)
325 ######### Упаковываем элементы ################
326 # Создаем основной вертикальный контейнер
327 main_Vbox = gtk.VBox(False, 4)
329 # Создаем вспомогательный горизонтальный контейнер для Надписи1,
330 # окошка ввода количества файлов и кнопки "Показать"
331 hbox1 = gtk.HBox(False, 5)
332 # Добавляем вышеперечисленные элементы во вспомогат. контейнер
333 hbox1.pack_start(label1, False, False, 5)
334 hbox1.pack_start(self.file_cnt, False, False, 0)
335 hbox1.pack_start(self.butt_start, True, True, 0)
336 hbox1.pack_start(self.butt_stop, True, True, 0)
337 hbox1.pack_start(self.propertiesBtn, True, True, 0)
339 # Добавляем элементы в основной контейнер
340 main_Vbox.pack_start(self.srch_p_entr, False, False, 0)
341 main_Vbox.pack_start(hbox1, False, False, 0)
342 scrollwind.add(self.treeview)
343 main_Vbox.pack_start(scrollwind, True, True, 0)
344 main_Vbox.pack_start(currFileFrm, False, False, 0)
349 """This function show main window of FindIT"""
354 ### Main call ##################################################################
356 if __name__ == '__main__':
357 gobject.set_application_name( _('FindIT') )
359 if platform == 'win32':
362 startpath = expanduser('~')
364 app = MainWindow(575, 345, startpath)