PropertiesDialog: moved init code to parent's init call
[findit] / src / findit.py
index 705ca67..dc64d92 100755 (executable)
@@ -1,27 +1,36 @@
 #!/usr/bin/env python
 # -*-coding: utf-8 -*-
 # vim: sw=4 ts=4 expandtab ai
+# pylint: disable-msg=C0301
+
+"""findIT: Gui prorgram to find various information.
+   At the moment it only finds largest files
+"""
 
 import gtk
 import gobject
 import pango
 from os import walk
 from os.path import join, abspath, normcase, basename, \
-                    isdir, getsize, getatime, getmtime
+                    isdir, getsize, getatime, getmtime, expanduser
 from heapq import nlargest
 import gettext
 import time
+from sys import platform
 
-try: import hildon; hildonFound = True
-except: hildonFound = False
+try: 
+    import hildon
+    HILDON = True
+except ImportError:
+    HILDON = False
 
 try:
     # Подразумевается, что ru/LC_MESSAGES/program.mo находится в текущем каталоге (sys.path[0])
     # Для стандартного /usr/share/locale писать gettext.translation('findit')
     #langRU = gettext.translation('findit', sys.path[0], languages=['ru'])
-    langRU = gettext.translation('findit')
-    langRU.install()
-except:
+    LANGRU = gettext.translation('findit')
+    LANGRU.install()
+except IOError:
     # Закомментировать перед использованием pygettext
     def _(text): 
         return text
@@ -31,17 +40,19 @@ except:
 
 # Функция которая возвращает строку из числа и единиц для столбца "Размер"("Size")
 def size_convert(size):
+    """Return string with file size in b or Kb or Mb or Gb or Tb."""
     for i, unit in enumerate(['%d b', '%.1f Kb', '%.2f Mb', '%.3f Gb', '%.4f Tb']):
         if size < 1024**(i+1):
             return unit % (size/1024.**i)
     return '>1024 Tb'
 
 # Функция поставляющая размер файла и путь к нему
-def filegetter(startpath, obj):
+def filegetter(startdir, obj):
+    """Generator of file sizes and paths based on os.walk."""
     # Список игнорируемых каталогов:
     ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
     # Проходим по всем папкам вглубь от заданного пути
-    for dirpath, dirnames, fnames in walk(startpath):
+    for dirpath, dirnames, fnames in walk(startdir):
     # Исключаем каталоги из поиска в соответствии со списком исключений
         for ign_dir in ignore_dirs[:]:
             for dirname in dirnames[:]:
@@ -52,7 +63,7 @@ def filegetter(startpath, obj):
         for fname in fnames:
             flpath = abspath(join(dirpath, fname))
             # Выводим текущий опрашиваемый файл в строку статуса
-            obj.currFileLbl.set_text(flpath)
+            obj.currfilelbl.set_text(flpath)
             # обновляем окно
             gtk.main_iteration()
             # Останавливаем цикл по нажатию кнопки стоп
@@ -61,14 +72,14 @@ def filegetter(startpath, obj):
                 raise StopIteration
             # Проверяем можем ли мы определить размер файла - иначе пропускаем его
             try:
-                flsize = getsize(flpath)
-            except:
+                # Возвращаем размер и полный путь файла
+                yield getsize(flpath), flpath
+            except OSError:
                 continue
-            # Возвращаем размер и полный путь файла
-            yield flsize, flpath
 
 # Fullscreen
 def toggle_fullscreen(obj):
+    """Switch fullscreen on/off."""
     if obj.fullscreen:
         obj.window.unfullscreen()
     else: 
@@ -77,18 +88,21 @@ def toggle_fullscreen(obj):
 
 # Нажатие на кнопку клавиатуры
 def on_key_press(obj, event):
-    if hildonFound and event.keyval == gtk.keysyms.F6:
+    """Key press callback."""
+    # Toggle fullscreen on Maemo when hw key is pressed
+    if HILDON and event.keyval == gtk.keysyms.F6:
         toggle_fullscreen(obj)
 
 ### Properties dialog ##########################################################
 
 class PropertiesDialog(gtk.Dialog):
-    def __init__(self, path, size, bytesize):
-        gtk.Dialog.__init__(self)
-        self.set_title( _('File properties') )
-        self.set_transient_for(app)
+    """File property dialog window."""
+
+    def __init__(self, app, path, size, bytesize):
+        """Create&show file properties dialog."""
+        gtk.Dialog.__init__(self, _('File properties'), app,
+            buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK))
         self.set_wmclass('PropertiesDialog', 'FindIT')
-        self.add_buttons(gtk.STOCK_OK, gtk.RESPONSE_OK)
         self.set_resizable(False)
 
         # Достаем свойства выбранного файла
@@ -103,21 +117,9 @@ class PropertiesDialog(gtk.Dialog):
         table.set_row_spacings(10)
 
         # Надписи (подпись: значение)
-        nameLbl = gtk.Label( _('Name') )
-        nameValueLbl = gtk.Label(name)
-
-        sizeLbl = gtk.Label( _('Size') )
-        sizeValueLbl = gtk.Label(size + ' (' + `bytesize` + ' b)')
-
-        accessLbl = gtk.Label( _('Opened') )
-        accessValueLbl = gtk.Label(access)
-
-        modifiedLbl = gtk.Label( _('Modified') )
-        modifiedValueLbl = gtk.Label(modified)
-
-        # Список надписей
-        lbls = [(nameLbl,   nameValueLbl),   (sizeLbl,     sizeValueLbl),
-                (accessLbl, accessValueLbl), (modifiedLbl, modifiedValueLbl)]
+        lbls = [(gtk.Label(_(name)), gtk.Label(value)) for name, value in 
+            [('Name', name), ('Size', "%s (%d b)" % (size, bytesize)),
+             ('Opened', access), ('Modified', modified)]]
 
         # Упаковка надписей в таблицу и выравнивание
         for i, lbl in enumerate(lbls):
@@ -136,9 +138,11 @@ class PropertiesDialog(gtk.Dialog):
 ### Main window ################################################################
 
 class MainWindow(gtk.Window):
+    """Main window class."""
 
     # Окно сообщения заданного типа с заданным текстом
     def mess_window(self, mestype, content):
+        """Show popup message window."""
         dialog = gtk.MessageDialog(parent=self, flags=gtk.DIALOG_MODAL,
                                    type=mestype, buttons=gtk.BUTTONS_OK,
                                    message_format=content)
@@ -149,12 +153,13 @@ class MainWindow(gtk.Window):
 
     # Функция выполняющаяся при нажатии на кнопку "Показать"
     def start_print(self, widget):
+        """Start file search. Button "Go" activate callback."""         
         self.start_path = self.srch_p_entr.get_text()
         # Проверяем правильное ли значение введено
         if isdir(self.start_path):
             self.butt_start.set_sensitive(False)
             self.butt_stop.set_sensitive(True)
-            self.propertiesBtn.set_sensitive(False)
+            self.propertiesbtn.set_sensitive(False)
             # Получаем значение количества файлов из SpinButton
             self.fl_cnt = int( self.file_cnt.get_value() )
             # Очищаем список
@@ -170,35 +175,40 @@ class MainWindow(gtk.Window):
                 # кто увидит скажите - нужна статистика
                 try: 
                     self.treestore.append(None, [fpath, size_convert(fsize), fsize])
-                except: 
-                    'error', fpath, size_convert(fsize), fsize
+                except SystemError:
+#                    print 'error', fpath, size_convert(fsize), fsize
+                    self.mess_window('error','Error in %s' % fpath)
             self.butt_start.set_sensitive(True)
             self.butt_stop.set_sensitive(False)
-            self.propertiesBtn.set_sensitive(True)
+            self.propertiesbtn.set_sensitive(True)
+            self.srch_p_entr.grab_focus()
         else:
             # Иначе выводим окошко с ошибкой
             self.mess_window('error', _('Invalid directory') )
 
     # Функция выполняющаяся при нажатии на кнопку "Стоп"
     def stop_print(self, widget):
+        """Stop search. "Stop" button clicked callback."""
         self.stopit = True
 
     # Функция выполняющаяся при нажатии на кнопку "Свойства файла"
     def show_properties_dialog(self, *args):
+        """Show property dialog window."""
         selection = self.treeview.get_selection()
-        (model, it) = selection.get_selected()
+        (model, item) = selection.get_selected()
         try:
-            path = model.get_value(it, 0)
-            size = model.get_value(it, 1)
-            bytesize = model.get_value(it, 2)
-        except:
+            path = model.get_value(item, 0)
+            size = model.get_value(item, 1)
+            bytesize = model.get_value(item, 2)
+        except (TypeError, ValueError):
             self.mess_window('error', _('Please select file') )
             return
-        PropertiesDialog(path, size, bytesize)
+        PropertiesDialog(self, path, size, bytesize)
 
     ### Window initialization ##################################################
 
     def __init__(self, win_width, win_height, st_path):
+        """Create MainWindow."""
         # Создаем новое окно
         gtk.Window.__init__(self)
         self.set_default_size(win_width, win_height)
@@ -215,7 +225,7 @@ class MainWindow(gtk.Window):
         self.start_path = st_path
         self.srch_p_entr.set_text(self.start_path)
         # Отключаем автокапитализацию(ввод первой буквы заглавной) на таблетке
-        if hildonFound:
+        if HILDON:
             self.srch_p_entr.set_property("hildon-input-mode", 'full')
         # Нажатие Enter в поле ввода
         self.srch_p_entr.connect("activate", self.start_print)
@@ -228,7 +238,7 @@ class MainWindow(gtk.Window):
         # 4. Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
         #    данные храняться в переменной self.fl_cnt
         self.fl_cnt = 10
-        if hildonFound:
+        if HILDON:
             self.file_cnt = hildon.NumberEditor(1, 99)
             self.file_cnt.set_value(self.fl_cnt)
         else:
@@ -246,9 +256,9 @@ class MainWindow(gtk.Window):
         self.stopit = False
 
         # 5.3 Кнопка "Свойства файла"
-        self.propertiesBtn = gtk.Button( _('File properties') )
-        self.propertiesBtn.connect('clicked', self.show_properties_dialog)
-        self.propertiesBtn.set_sensitive(False)
+        self.propertiesbtn = gtk.Button( _('File properties') )
+        self.propertiesbtn.connect('clicked', self.show_properties_dialog)
+        self.propertiesbtn.set_sensitive(False)
 
         # 6. Закладки
 
@@ -264,7 +274,7 @@ class MainWindow(gtk.Window):
         self.treeview.set_headers_visible(1)
         self.treeview.connect('row-activated', self.show_properties_dialog)
 
-        self.treestore.append(None, ['','', 0])
+        self.treestore.append(None, ['', '', 0])
 
         # Создаем и настраиваем колонку с размером файла
         size_col = gtk.TreeViewColumn( _('Size') )
@@ -288,16 +298,16 @@ class MainWindow(gtk.Window):
         # 6.2 Надпись "Найти"
 
         # 6.3 Строка выводящая текущий осматриваемый файл
-        self.currFileLbl = gtk.Label()
-        self.currFileLbl.set_alignment(0, 0.5)
-        self.currFileLbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
-        self.currFileLbl.set_padding(2, 2)
-        currFileFrm = gtk.Frame()
-        currFileFrm.add(self.currFileLbl)
+        self.currfilelbl = gtk.Label()
+        self.currfilelbl.set_alignment(0, 0.5)
+        self.currfilelbl.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
+        self.currfilelbl.set_padding(2, 2)
+        currfilefrm = gtk.Frame()
+        currfilefrm.add(self.currfilelbl)
 
         #########  Упаковываем элементы ################
         # Создаем основной вертикальный контейнер
-        main_Vbox = gtk.VBox(False, 4)
+        main_vbox = gtk.VBox(False, 4)
 
         # Создаем вспомогательный горизонтальный контейнер для Надписи1,
         # окошка ввода количества файлов и кнопки "Показать"
@@ -307,26 +317,34 @@ class MainWindow(gtk.Window):
         hbox1.pack_start(self.file_cnt, False, False, 0)
         hbox1.pack_start(self.butt_start, True, True, 0)
         hbox1.pack_start(self.butt_stop, True, True, 0)
-        hbox1.pack_start(self.propertiesBtn, True, True, 0)
+        hbox1.pack_start(self.propertiesbtn, True, True, 0)
 
         # Добавляем элементы в основной контейнер
-        main_Vbox.pack_start(self.srch_p_entr, False, False, 0)
-        main_Vbox.pack_start(hbox1, False, False, 0)
+        main_vbox.pack_start(self.srch_p_entr, False, False, 0)
+        main_vbox.pack_start(hbox1, False, False, 0)
         scrollwind.add(self.treeview)
-        main_Vbox.pack_start(scrollwind, True, True, 0)
-        main_Vbox.pack_start(currFileFrm, False, False, 0)
+        main_vbox.pack_start(scrollwind, True, True, 0)
+        main_vbox.pack_start(currfilefrm, False, False, 0)
 
-        self.add(main_Vbox)
+        self.add(main_vbox)
 
     def run(self):
+        """Show all widgets and run gtk.main()."""
         self.show_all()
         gtk.main()
 
 
 ### Main call ##################################################################
-
-if __name__ == '__main__':
+def main():
+    """Main function."""
     gobject.set_application_name( _('FindIT') )
-    app = MainWindow(575, 345, '.')
-    app.run()
 
+    if platform == 'win32':
+        startpath = 'c:\\'
+    else:
+        startpath = expanduser('~')
+
+    MainWindow(575, 345, startpath).run()
+
+if __name__ == '__main__':
+    main()