--- /dev/null
+#!/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, expanduser
+from heapq import nlargest
+import gettext
+import time
+from sys import platform
+
+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 IOError:
+ # Закомментировать перед использованием pygettext
+ def _(text):
+ return text
+
+
+### Common functions ###########################################################
+
+# Функция которая возвращает строку из числа и единиц для столбца "Размер"("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(startdir, obj):
+ """Generator of file sizes and paths based on os.walk."""
+ # Список игнорируемых каталогов:
+ ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
+ # Проходим по всем папкам вглубь от заданного пути
+ for dirpath, dirnames, fnames in walk(startdir):
+ # Исключаем каталоги из поиска в соответствии со списком исключений
+ for ign_dir in ignore_dirs[:]:
+ for dirname in dirnames[:]:
+ if ign_dir == normcase(join(abspath(dirpath), dirname)):
+ dirnames.remove(dirname)
+ ignore_dirs.remove(ign_dir)
+
+ for fname in fnames:
+ flpath = abspath(join(dirpath, fname))
+ # Выводим текущий опрашиваемый файл в строку статуса
+ obj.currfilelbl.set_text(flpath)
+ # обновляем окно
+ gtk.main_iteration()
+ # Останавливаем цикл по нажатию кнопки стоп
+ if obj.stopit:
+ obj.stopit = False
+ raise StopIteration
+ # Проверяем можем ли мы определить размер файла - иначе пропускаем его
+ try:
+ # Возвращаем размер и полный путь файла
+ yield getsize(flpath), flpath
+ except OSError:
+ continue
+
+# Fullscreen
+def toggle_fullscreen(obj):
+ """Switch fullscreen on/off."""
+ if obj.fullscreen:
+ obj.window.unfullscreen()
+ else:
+ obj.window.fullscreen()
+ obj.fullscreen = not obj.fullscreen
+
+# Нажатие на кнопку клавиатуры
+def on_key_press(obj, event):
+ """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):
+ """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.set_resizable(False)
+
+ # Достаем свойства выбранного файла
+ name = basename(path)
+ access = time.strftime('%x %X', time.localtime(getatime(path)))
+ modified = time.strftime('%x %X', time.localtime(getmtime(path)))
+
+ # Таблица надписей
+ table = gtk.Table()
+ table.set_border_width(10)
+ table.set_col_spacings(10)
+ table.set_row_spacings(10)
+
+ # Надписи (подпись: значение)
+ 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):
+ name, value = lbl
+ table.attach(name, 0, 1, i, i+1)
+ table.attach(value, 1, 2, i, i+1)
+ name.set_alignment(1, 0.5)
+ value.set_alignment(0, 0.5)
+
+ # Упаковка таблицы в vbox диалога
+ self.vbox.add(table)
+ self.show_all()
+ self.run()
+ self.destroy()
+
+
+### About dialog ###############################################################
+
+class AboutDialog(gtk.AboutDialog):
+ """About dialog window."""
+
+ def __init__(self, *args):
+ """Create&show about dialog."""
+ gtk.AboutDialog.__init__(self)
+ self.set_wmclass('AboutDialog', 'FindIT')
+
+ self.set_authors([ 'Alex Taker\n * Email: alteker@gmail.com\n',
+ 'Eugene Gagarin\n * Email: mosfet07@ya.ru\n',
+ 'Alexandr Popov\n * Email: popov2al@gmail.com' ])
+
+ self.set_comments('Tool for find some information on computer.')
+ self.set_version('0.1.0')
+ self.set_license("This program is free software; you can redistribute it and/or\nmodify it under the terms of the GNU General Public License\nas published by the Free Software Foundation; either version 3\nof the License, or (at your option) any later version.")
+ self.set_copyright('')
+ self.set_website('')
+
+ self.show_all()
+ self.run()
+ self.destroy()
+
+### 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)
+ dialog.set_wmclass('ErrorDialog', 'FindIT')
+ dialog.set_title( _('Error!') )
+ dialog.run()
+ dialog.destroy()
+
+ # Функция выполняющаяся при нажатии на кнопку "Показать"
+ def start_print(self, widget):
+ """Start file search. Button "Go" activate callback."""
+# self.start_path = self.srch_p_entr.get_text()
+ self.start_path = self.srch_p_btn.get_current_folder()
+ # Проверяем правильное ли значение введено
+ if isdir(self.start_path):
+ self.butt_start.set_sensitive(False)
+ self.butt_stop.set_sensitive(True)
+ self.propertiesbtn.set_sensitive(False)
+ # Получаем значение количества файлов из SpinButton
+ self.fl_cnt = int( self.file_cnt.get_value() )
+ # Очищаем список
+ self.treestore.clear()
+ self.treeview.columns_autosize()
+ # Получаем нужное количество самых больших файлов
+ for fsize, fpath in nlargest(self.fl_cnt, filegetter(self.start_path, self)):
+ # Возвращаем значения в treeview в таком порядке - путь,
+ # размер в Мб строкой и размер в байтах
+ # self.treestore.append(None, [fpath.replace(self.start_path,'', 1),
+ # size_convert(fsize), fsize])
+
+ # Выдает какую-то перманентную ошибку при присвоении значений treestore -
+ # кто увидит скажите - нужна статистика
+ try:
+ self.treestore.append(None, [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.srch_p_entr.grab_focus()
+ self.srch_p_btn.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, item) = selection.get_selected()
+ try:
+ 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(self, path, size, bytesize)
+
+ # Создание меню
+ def create_menu(self):
+ """ Create main menu """
+ menubar = gtk.MenuBar()
+
+ # File menu
+ fileitem = gtk.MenuItem( _('_File') ) # Файл
+ filemenu = gtk.Menu()
+ fileitem.set_submenu(filemenu)
+
+ open_menuitem = gtk.ImageMenuItem(gtk.STOCK_OPEN)
+ delete_menuitem = gtk.ImageMenuItem(gtk.STOCK_DELETE)
+ properties_menuitem = gtk.ImageMenuItem(gtk.STOCK_PROPERTIES)
+ quit_menuitem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
+ filemenu.add(open_menuitem)
+ filemenu.add(delete_menuitem)
+ filemenu.add(properties_menuitem)
+ filemenu.add(quit_menuitem)
+ properties_menuitem.connect('activate', self.show_properties_dialog)
+ quit_menuitem.connect('activate', gtk.main_quit)
+
+ # View menu
+ viewitem = gtk.MenuItem( _('_View') ) # Вид
+ viewmenu = gtk.Menu()
+
+ # Help menu
+ helpitem = gtk.MenuItem( _('_Help') ) # Помощь
+ helpmenu = gtk.Menu()
+ helpitem.set_submenu(helpmenu)
+
+ about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
+ helpmenu.add(about_menuitem)
+ about_menuitem.connect('activate', AboutDialog)
+
+ # Packing
+ menubar.add(fileitem)
+ menubar.add(viewitem)
+ menubar.add(helpitem)
+
+ return menubar
+
+# def create_hildon_menu(self):
+# """ Create Hildon main menu """
+
+ ### 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)
+ self.set_border_width(4)
+ self.fullscreen = False
+ self.connect('delete_event', gtk.main_quit)
+ self.connect('key-press-event', on_key_press)
+ self.set_wmclass('MainWindow', 'FindIT')
+
+ ######### Добавляем элементы ################
+ # 1. Строка ввода каталога с которого начинать поиск
+
+ # 2. Кнопка "Обзор"
+ self.srch_p_btn = gtk.FileChooserButton( _('Browse...') )
+ self.srch_p_btn.set_action('select-folder')
+
+ # 3. Надпись1 "Количество отображаемых файлов:"
+ label1 = gtk.Label( _('Files quantity') )
+
+ # 4. Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
+ # данные храняться в переменной self.fl_cnt
+ self.fl_cnt = 10
+ if HILDON:
+ self.file_cnt = hildon.NumberEditor(1, 99)
+ self.file_cnt.set_value(self.fl_cnt)
+ else:
+ adj = gtk.Adjustment(self.fl_cnt, 1, 65536, 1, 5, 0)
+ self.file_cnt = gtk.SpinButton(adj, 0, 0)
+
+ # 5.1 Кнопка "Показать"
+ self.butt_start = gtk.Button( _('Go') )
+ self.butt_start.connect('released', self.start_print)
+
+ # 5.2 Кнопка "Остановить"
+ self.butt_stop = gtk.Button( _('Stop') )
+ self.butt_stop.set_sensitive(False)
+ self.butt_stop.connect('clicked', self.stop_print)
+ self.stopit = False
+
+ # 5.3 Кнопка "Свойства файла"
+ self.propertiesbtn = gtk.Button( _('File properties') )
+ self.propertiesbtn.connect('clicked', self.show_properties_dialog)
+ self.propertiesbtn.set_sensitive(False)
+
+ # 6. Закладки
+
+ # 6.1 Список файлов
+ scrollwind = gtk.ScrolledWindow()
+ scrollwind.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ # Определяем переменную в которой будет храниться выводимый список
+ self.treestore = gtk.TreeStore(str, str, int)
+ self.treeview = gtk.TreeView(self.treestore)
+ # На таблетке не отображаються заголовки столбцов по умолчанию -
+ # след строка заставляет их отображаться принудительно
+ self.treeview.set_headers_visible(1)
+ self.treeview.connect('row-activated', self.show_properties_dialog)
+
+ self.treestore.append(None, ['', '', 0])
+
+ # Создаем и настраиваем колонку с размером файла
+ size_col = gtk.TreeViewColumn( _('Size') )
+ cell = gtk.CellRendererText()
+ cell.set_property('width', 90)
+ size_col.pack_start(cell, True)
+ size_col.add_attribute(cell, 'text', 1)
+ self.treeview.append_column(size_col)
+ # Создаем и настраиваем колонку с именем файла
+ path_col = gtk.TreeViewColumn( _('Path') )
+ cell2 = gtk.CellRendererText()
+ path_col.pack_start(cell2, True)
+ path_col.add_attribute(cell2, 'text', 0)
+ self.treeview.append_column(path_col)
+
+ # Добавляем сортировку для колонок
+ self.treeview.set_search_column(1)
+ path_col.set_sort_column_id(0)
+ size_col.set_sort_column_id(2)
+
+ # 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)
+
+ # 7 Меню
+ if HILDON:
+ main_menu = self.create_hildon_menu()
+ else:
+ main_menu = self.create_menu()
+
+ ######### Упаковываем элементы ################
+ # Создаем основной вертикальный контейнер
+ main_vbox = gtk.VBox(False, 4)
+
+ # Создаем вспомогательный горизонтальный контейнер для Надписи1,
+ # окошка ввода количества файлов и кнопки "Показать"
+ hbox1 = gtk.HBox(False, 5)
+ # Добавляем вышеперечисленные элементы во вспомогат. контейнер
+ hbox1.pack_start(label1, False, False, 5)
+ 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)
+
+ # Добавляем элементы в основной контейнер
+ main_vbox.pack_start(main_menu, False, False, 0)
+# main_vbox.pack_start(self.srch_p_entr, False, False, 0)
+ main_vbox.pack_start(self.srch_p_btn, 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)
+
+ self.add(main_vbox)
+
+ def run(self):
+ """Show all widgets and run gtk.main()."""
+ self.show_all()
+ gtk.main()
+
+
+### Main call ##################################################################
+def main():
+ """Main function."""
+ gobject.set_application_name( _('FindIT') )
+
+ if platform == 'win32':
+ startpath = 'c:\\'
+ else:
+ startpath = expanduser('~')
+
+ MainWindow(575, 345, startpath).run()
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+#!/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, expanduser
+from heapq import nlargest
+import gettext
+import time
+from sys import platform
+
+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 IOError:
+ # Закомментировать перед использованием pygettext
+ def _(text):
+ return text
+
+
+### Common functions ###########################################################
+
+# Функция которая возвращает строку из числа и единиц для столбца "Размер"("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(startdir, obj):
+ """Generator of file sizes and paths based on os.walk."""
+ # Список игнорируемых каталогов:
+ ignore_dirs = ['/dev', '/proc', '/sys', '/mnt']
+ # Проходим по всем папкам вглубь от заданного пути
+ for dirpath, dirnames, fnames in walk(startdir):
+ # Исключаем каталоги из поиска в соответствии со списком исключений
+ for ign_dir in ignore_dirs[:]:
+ for dirname in dirnames[:]:
+ if ign_dir == normcase(join(abspath(dirpath), dirname)):
+ dirnames.remove(dirname)
+ ignore_dirs.remove(ign_dir)
+
+ for fname in fnames:
+ flpath = abspath(join(dirpath, fname))
+ # Выводим текущий опрашиваемый файл в строку статуса
+ obj.currfilelbl.set_text(flpath)
+ # обновляем окно
+ gtk.main_iteration()
+ # Останавливаем цикл по нажатию кнопки стоп
+ if obj.stopit:
+ obj.stopit = False
+ raise StopIteration
+ # Проверяем можем ли мы определить размер файла - иначе пропускаем его
+ try:
+ # Возвращаем размер и полный путь файла
+ yield getsize(flpath), flpath
+ except OSError:
+ continue
+
+# Fullscreen
+def toggle_fullscreen(obj):
+ """Switch fullscreen on/off."""
+ if obj.fullscreen:
+ obj.window.unfullscreen()
+ else:
+ obj.window.fullscreen()
+ obj.fullscreen = not obj.fullscreen
+
+# Нажатие на кнопку клавиатуры
+def on_key_press(obj, event):
+ """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):
+ """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.set_resizable(False)
+
+ # Достаем свойства выбранного файла
+ name = basename(path)
+ access = time.strftime('%x %X', time.localtime(getatime(path)))
+ modified = time.strftime('%x %X', time.localtime(getmtime(path)))
+
+ # Таблица надписей
+ table = gtk.Table()
+ table.set_border_width(10)
+ table.set_col_spacings(10)
+ table.set_row_spacings(10)
+
+ # Надписи (подпись: значение)
+ 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):
+ name, value = lbl
+ table.attach(name, 0, 1, i, i+1)
+ table.attach(value, 1, 2, i, i+1)
+ name.set_alignment(1, 0.5)
+ value.set_alignment(0, 0.5)
+
+ # Упаковка таблицы в vbox диалога
+ self.vbox.add(table)
+ self.show_all()
+ self.run()
+ self.destroy()
+
+
+### About dialog ###############################################################
+
+class AboutDialog(gtk.AboutDialog):
+ """About dialog window."""
+
+ def __init__(self, *args):
+ """Create&show about dialog."""
+ gtk.AboutDialog.__init__(self)
+ self.set_wmclass('AboutDialog', 'FindIT')
+
+ self.set_authors([ 'Alex Taker\n * Email: alteker@gmail.com\n',
+ 'Eugene Gagarin\n * Email: mosfet07@ya.ru\n',
+ 'Alexandr Popov\n * Email: popov2al@gmail.com' ])
+
+ self.set_comments('Tool for find some information on computer.')
+ self.set_version('0.1.0')
+ self.set_license("This program is free software; you can redistribute it and/or\nmodify it under the terms of the GNU General Public License\nas published by the Free Software Foundation; either version 3\nof the License, or (at your option) any later version.")
+ self.set_copyright('')
+ self.set_website('')
+
+ self.show_all()
+ self.run()
+ self.destroy()
+
+### 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)
+ dialog.set_wmclass('ErrorDialog', 'FindIT')
+ dialog.set_title( _('Error!') )
+ dialog.run()
+ dialog.destroy()
+
+ # Функция выполняющаяся при нажатии на кнопку "Показать"
+ 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)
+ # Получаем значение количества файлов из SpinButton
+ self.fl_cnt = int( self.file_cnt.get_value() )
+ # Очищаем список
+ self.treestore.clear()
+ self.treeview.columns_autosize()
+ # Получаем нужное количество самых больших файлов
+ for fsize, fpath in nlargest(self.fl_cnt, filegetter(self.start_path, self)):
+ # Возвращаем значения в treeview в таком порядке - путь,
+ # размер в Мб строкой и размер в байтах
+ # self.treestore.append(None, [fpath.replace(self.start_path,'', 1),
+ # size_convert(fsize), fsize])
+
+ # Выдает какую-то перманентную ошибку при присвоении значений treestore -
+ # кто увидит скажите - нужна статистика
+ try:
+ self.treestore.append(None, [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.srch_p_entr.grab_focus()
+ self.srch_p_btn.grab_focus()
+ else:
+ # Иначе выводим окошко с ошибкой
+ self.mess_window('error', _('Invalid directory') )
+
+ # Функция выполняющаяся при нажатии на кнопку "Стоп"
+ def stop_print(self, widget):
+ """Stop search. "Stop" button clicked callback."""
+ self.stopit = True
+
+ # Функция выполняющаяся при нажатии на кнопку "Обзор"
+ def browse(self, widget):
+ """Open directory browser. "Browse" button clicked callback."""
+ dialog = gtk.FileChooserDialog( title=_('Choose directory'),
+ parent=self,
+ action='select-folder',
+ buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) )
+ dialog.set_current_folder(self.srch_p_entr.get_text())
+ dialog.show_all()
+ response = dialog.run()
+ if response == gtk.RESPONSE_OK:
+ self.srch_p_entr.set_text(dialog.get_filename())
+ dialog.destroy()
+
+
+ # Функция выполняющаяся при нажатии на кнопку "Свойства файла"
+ def show_properties_dialog(self, *args):
+ """Show property dialog window."""
+ selection = self.treeview.get_selection()
+ (model, item) = selection.get_selected()
+ try:
+ 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(self, path, size, bytesize)
+
+ # Создание меню
+ def create_menu(self):
+ """ Create main menu """
+ menubar = gtk.MenuBar()
+
+ # File menu
+ fileitem = gtk.MenuItem( _('_File') ) # Файл
+ filemenu = gtk.Menu()
+ fileitem.set_submenu(filemenu)
+
+ open_menuitem = gtk.ImageMenuItem(gtk.STOCK_OPEN)
+ delete_menuitem = gtk.ImageMenuItem(gtk.STOCK_DELETE)
+ properties_menuitem = gtk.ImageMenuItem(gtk.STOCK_PROPERTIES)
+ quit_menuitem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
+ filemenu.add(open_menuitem)
+ filemenu.add(delete_menuitem)
+ filemenu.add(properties_menuitem)
+ filemenu.add(quit_menuitem)
+ properties_menuitem.connect('activate', self.show_properties_dialog)
+ quit_menuitem.connect('activate', gtk.main_quit)
+
+ # View menu
+ viewitem = gtk.MenuItem( _('_View') ) # Вид
+ viewmenu = gtk.Menu()
+
+ # Help menu
+ helpitem = gtk.MenuItem( _('_Help') ) # Помощь
+ helpmenu = gtk.Menu()
+ helpitem.set_submenu(helpmenu)
+
+ about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
+ helpmenu.add(about_menuitem)
+ about_menuitem.connect('activate', AboutDialog)
+
+ # Packing
+ menubar.add(fileitem)
+ menubar.add(viewitem)
+ menubar.add(helpitem)
+
+ return menubar
+
+# def create_hildon_menu(self):
+# """ Create Hildon main menu """
+
+ ### 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)
+ self.set_border_width(4)
+ self.fullscreen = False
+ self.connect('delete_event', gtk.main_quit)
+ self.connect('key-press-event', on_key_press)
+ self.set_wmclass('MainWindow', 'FindIT')
+
+ ######### Добавляем элементы ################
+ # 1. Строка ввода каталога с которого начинать поиск
+ # переменная в которой храниться стартовый каталог = self.start_path
+ self.srch_p_entr = gtk.Entry()
+ self.start_path = st_path
+ self.srch_p_entr.set_text(self.start_path)
+ # Отключаем автокапитализацию(ввод первой буквы заглавной) на таблетке
+ if HILDON:
+ self.srch_p_entr.set_property('hildon-input-mode', 'full')
+ # Нажатие Enter в поле ввода
+ self.srch_p_entr.connect('activate', self.start_print)
+
+ # 2. Кнопка "Обзор"
+ self.srch_p_btn = gtk.Button('Browse...')
+ self.srch_p_btn.connect('clicked', self.browse)
+
+ # 3. Надпись1 "Количество отображаемых файлов:"
+ label1 = gtk.Label( _('Files quantity') )
+
+ # 4. Окошко ввода количества файлов, мин значение=1 макс=65536 по умолчанию 10
+ # данные храняться в переменной self.fl_cnt
+ self.fl_cnt = 10
+ if HILDON:
+ self.file_cnt = hildon.NumberEditor(1, 99)
+ self.file_cnt.set_value(self.fl_cnt)
+ else:
+ adj = gtk.Adjustment(self.fl_cnt, 1, 65536, 1, 5, 0)
+ self.file_cnt = gtk.SpinButton(adj, 0, 0)
+
+ # 5.1 Кнопка "Показать"
+ self.butt_start = gtk.Button( _('Go') )
+ self.butt_start.connect('released', self.start_print)
+
+ # 5.2 Кнопка "Остановить"
+ self.butt_stop = gtk.Button( _('Stop') )
+ self.butt_stop.set_sensitive(False)
+ self.butt_stop.connect('clicked', self.stop_print)
+ self.stopit = False
+
+ # 5.3 Кнопка "Свойства файла"
+ self.propertiesbtn = gtk.Button( _('File properties') )
+ self.propertiesbtn.connect('clicked', self.show_properties_dialog)
+ self.propertiesbtn.set_sensitive(False)
+
+ # 6. Закладки
+
+ # 6.1 Список файлов
+ scrollwind = gtk.ScrolledWindow()
+ scrollwind.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ # Определяем переменную в которой будет храниться выводимый список
+ self.treestore = gtk.TreeStore(str, str, int)
+ self.treeview = gtk.TreeView(self.treestore)
+ # На таблетке не отображаються заголовки столбцов по умолчанию -
+ # след строка заставляет их отображаться принудительно
+ self.treeview.set_headers_visible(1)
+ self.treeview.connect('row-activated', self.show_properties_dialog)
+
+ self.treestore.append(None, ['', '', 0])
+
+ # Создаем и настраиваем колонку с размером файла
+ size_col = gtk.TreeViewColumn( _('Size') )
+ cell = gtk.CellRendererText()
+ cell.set_property('width', 90)
+ size_col.pack_start(cell, True)
+ size_col.add_attribute(cell, 'text', 1)
+ self.treeview.append_column(size_col)
+ # Создаем и настраиваем колонку с именем файла
+ path_col = gtk.TreeViewColumn( _('Path') )
+ cell2 = gtk.CellRendererText()
+ path_col.pack_start(cell2, True)
+ path_col.add_attribute(cell2, 'text', 0)
+ self.treeview.append_column(path_col)
+
+ # Добавляем сортировку для колонок
+ self.treeview.set_search_column(1)
+ path_col.set_sort_column_id(0)
+ size_col.set_sort_column_id(2)
+
+ # 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)
+
+ # 7 Меню
+ if HILDON:
+ main_menu = self.create_hildon_menu()
+ else:
+ main_menu = self.create_menu()
+
+ ######### Упаковываем элементы ################
+ # Создаем основной вертикальный контейнер
+ main_vbox = gtk.VBox(False, 4)
+
+ # Создаем вспомогательный горизонтальный контейнер для Надписи1,
+ # окошка ввода количества файлов и кнопки "Показать"
+ hbox1 = gtk.HBox(False, 5)
+ # Добавляем вышеперечисленные элементы во вспомогат. контейнер
+ hbox1.pack_start(label1, False, False, 5)
+ 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)
+
+ hbox2 = gtk.HBox(False, 5)
+ hbox2.pack_start(self.srch_p_entr, True, True, 0)
+ hbox2.pack_start(self.srch_p_btn, False, False, 0)
+
+ # Добавляем элементы в основной контейнер
+ main_vbox.pack_start(main_menu, False, False, 0)
+# main_vbox.pack_start(self.srch_p_entr, False, False, 0)
+# main_vbox.pack_start(self.srch_p_btn, False, False, 0)
+ main_vbox.pack_start(hbox2, 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)
+
+ self.add(main_vbox)
+
+ def run(self):
+ """Show all widgets and run gtk.main()."""
+ self.show_all()
+ gtk.main()
+
+
+### Main call ##################################################################
+def main():
+ """Main function."""
+ gobject.set_application_name( _('FindIT') )
+
+ if platform == 'win32':
+ startpath = 'c:\\'
+ else:
+ startpath = expanduser('~')
+
+ MainWindow(575, 345, startpath).run()
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+from gtkmvc import Controller
+import gtk
+import gobject
+
+class AboutCtrl(Controller):
+ """Controller of 'About' dialog. It handles the filling dialog and
+ the close button."""
+
+ def __init__(self, model):
+ Controller.__init__(self, model)
+ return
+
+ def register_view(self, view):
+ """Loads the text taking it from the model."""
+
+ Controller.register_view(self, view)
+ self.view.set_progname(self.model.progname)
+ self.view.set_version(self.model.version)
+# self.view.set_authors(self.model.authors)
+ self.view.set_comments(self.model.comments)
+ self.view.set_license(self.model.license)
+ return
+
+ # -----------------------------------------------------
+ # user callbacks
+ # -----------------------------------------------------
+
+ # -----------------------------------------------------
+ # gtk signals
+ # -----------------------------------------------------
+ #def on_dialog_about_delete_event(self, win, event):
+ # return True
+
+ #def on_button_close_clicked(self, button):
+ # return
+
+ # -----------------------------------------------------
+ # observable properties
+ # -----------------------------------------------------
+# def property_credits_value_change(self, model, old, new):
+# self.view.set_text(new)
+# return
+
+ pass # end of class
--- /dev/null
+from gtkmvc import Controller
+import gtk
+
+from about import AboutCtrl
+from views.about import AboutView
+
+
+class ApplicationCtrl(Controller):
+ """Controller of the top-level window (application)"""
+
+ def __init__(self, model):
+ Controller.__init__(self, model)
+ return
+
+ def register_view(self, view):
+ """Creates treeview columns, and connect missing signals"""
+ Controller.register_view(self, view)
+
+ # connects the signals:
+ self.view['main_window'].connect('destroy', gtk.main_quit)
+ self.view['about_btn'].connect('clicked', self.on_tb_about_clicked)
+ self.view['quit_btn'].connect('clicked', self.on_tb_quit_clicked)
+ return
+
+ # -----------------------------------------------------
+ # user callbacks
+ # -----------------------------------------------------
+
+ def quit(self):
+ gtk.main_quit()
+ return
+
+ # -----------------------------------------------------
+ # gtk signals
+ # -----------------------------------------------------
+
+ def on_tb_about_clicked(self, tb):
+ c = AboutCtrl(self.model.about)
+ v = AboutView(c)
+ v.run() # this runs in modal mode
+ return
+
+ def on_tb_quit_clicked(self, bt):
+ self.quit()
+
+ # -----------------------------------------------------
+ # observable properties
+ # -----------------------------------------------------
+
+ pass # end of class
--- /dev/null
+#!/usr/bin/env python
+# -*-coding: utf-8 -*-
+# vim: sw=4 ts=4 expandtab ai
+# pylint: disable-msg=C0301
+
+
+__progname__ = 'FindIT'
+__version__ = '0.2.0'
+
+get_ui = 'console'
+
+def main():
+
+ from models.application import ApplicationModel as MyModel
+ from controllers.application import ApplicationCtrl as MyCtrl
+ from views.application import ApplicationView as MyView
+
+ import gtk
+
+ m = MyModel()
+ c = MyCtrl(m)
+ v = MyView(c)
+
+ gtk.main()
+ return
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+from gtkmvc import Model
+
+from __main__ import __version__, __progname__
+
+
+class AboutModel(Model):
+
+ # Observable properties
+ __properties__ = {
+ 'authors' : '',
+ 'comments' : '',
+ 'license' : '',
+ }
+
+ def __init__(self):
+ Model.__init__(self)
+
+ self.progname = __progname__
+ self.version = __version__
+
+ self.authors = [ 'Alex Taker\n * Email: alteker@gmail.com\n',
+ 'Eugene Gagarin\n * Email: mosfet07@ya.ru\n',
+ 'Alexandr Popov\n * Email: popov2al@gmail.com' ]
+
+ self.comments = 'Tool for find some information on computer.'
+
+ self.license = \
+'This program is free software; you can redistribute it and/or\nmodify it \
+under the terms of the GNU General Public License\nas published by the Free \
+Software Foundation; either version 3\nof the License, or (at your option) \
+any later version.'
+
+ return
+
+ pass # end of class
--- /dev/null
+from gtkmvc import Model
+import os.path
+
+from about import AboutModel
+
+
+class ApplicationModel(Model):
+
+ def __init__(self):
+ Model.__init__(self)
+
+ self.about = AboutModel()
+ return
+
+ pass # end of class
--- /dev/null
+from gtkmvc import View
+import gtk
+
+
+class AboutView(View):
+ """This is the view for the 'About' dialog"""
+
+ def __init__(self, ctrl):
+ View.__init__(self, ctrl, register=False)
+
+ dialog = gtk.AboutDialog()
+ self['dialog_about'] = dialog
+ ctrl.register_view(self)
+
+ return
+
+ def set_progname(self, text):
+ self['dialog_about'].set_name(text)
+ return
+
+ def set_version(self, text):
+ self['dialog_about'].set_version(text)
+ return
+
+ def set_authors(self, text):
+ self['dialog_about'].set_authors(text)
+ return
+
+ def set_comments(self, text):
+ self['dialog_about'].set_comments(text)
+ return
+
+ def set_license(self, text):
+ self['dialog_about'].set_license(text)
+ return
+
+ def run(self):
+ res = self['dialog_about'].run()
+ self['dialog_about'].destroy()
+ return res
+
+ pass # end of class
--- /dev/null
+from gtkmvc import View
+import os.path
+import gtk
+
+
+class ApplicationView(View):
+ """A view for the top level window (application)"""
+
+ def __init__(self, ctrl):
+ View.__init__(self, ctrl, register=False)
+
+ window = gtk.Window()
+ window.set_border_width(4)
+
+ hbox = gtk.HBox(4, True)
+
+ about_btn = gtk.Button('About')
+ quit_btn = gtk.Button('Exit')
+
+ about_btn.set_size_request(100, 150)
+ quit_btn.set_size_request(100, 150)
+
+ hbox.pack_start(about_btn, True, True, 0)
+ hbox.pack_start(quit_btn, True, True, 0)
+
+ window.add(hbox)
+ window.show_all()
+
+ self['main_window'] = window
+ self['about_btn'] = about_btn
+ self['quit_btn'] = quit_btn
+
+ ctrl.register_view(self)
+ return
+
+ pass # end of class