[Syncropated-commits] r157 - trunk/src
zimmerle at garage.maemo.org
zimmerle at garage.maemo.org
Tue Jan 30 00:05:12 EET 2007
Author: zimmerle
Date: 2007-01-30 00:05:10 +0200 (Tue, 30 Jan 2007)
New Revision: 157
Added:
trunk/src/FileTree.py
Log:
first FileTree.py import
Added: trunk/src/FileTree.py
===================================================================
--- trunk/src/FileTree.py 2007-01-29 21:10:58 UTC (rev 156)
+++ trunk/src/FileTree.py 2007-01-29 22:05:10 UTC (rev 157)
@@ -0,0 +1,425 @@
+# Syncropated
+#
+# Copyright (c) 2006 INdT (Instituto Nokia de Technologia)
+#
+# Author: Felipe Zimmerle <felipe at zimmerle.org>
+# Kenneth Rohde Christiansen <kenneth.christiansen at gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+
+import gobject
+import gtk
+import pygtk
+import sys
+import gtk.glade
+import os
+import pango
+from Utils import Utils
+from Icons import Icons
+from Logger import Logger
+from Configuration import Configuration
+
+log = Logger()
+icons = Icons()
+config = Configuration()
+utils = Utils()
+
+
+class FileTree(gobject.GObject):
+ """
+ Start the FileTree Selector dialog.
+
+ And handle all relative dialog information.
+
+ """
+
+ # FIXME: When the user expand a directory, its should focus the treeview at the new
+ # expanded folder.
+
+ SELECTED_PATH_PANGO_STRING_START = '<span foreground="blue" weight="bold">'
+ SELECTED_PATH_PANGO_STRING_END = '</span>'
+
+ INSIDE_SELECTED_PATH_PANGO_STRING_START = '<span foreground="grey">'
+ INSIDE_SELECTED_PATH_PANGO_STRING_END = '</span>'
+
+ __path_nopermission = []
+ __path_custon_icon = { '/root': 'go-home' }
+
+ __selected_dirs = []
+
+ def __init__(self, media_type):
+ gobject.GObject.__init__(self)
+ self.__media_type = media_type
+
+ self.__selected_dirs = config.getValue('media_' + media_type + '_paths')
+ if self.__selected_dirs == None:
+ self.__selected_dirs = []
+ else:
+ self.__selected_dirs = self.__selected_dirs.split(';')
+
+ self.__path_custon_icon[os.path.expanduser('~')] = 'go-home'
+
+ log.debug('FileTree :: Selected dirs: ' + str(self.__selected_dirs))
+
+ self.start()
+
+ def start(self):
+ xml = gtk.glade.XML(utils.get_glade_fullpath('filetree.glade'))
+ tree_view = xml.get_widget('treeview1')
+ tree_view.set_size_request(400, 320)
+
+ self.__window = xml.get_widget('filetree')
+
+ model = tree_view.get_model()
+ model = gtk.TreeStore(gobject.TYPE_BOOLEAN, gtk.gdk.Pixbuf,
+ gobject.TYPE_STRING, gobject.TYPE_STRING)
+ tree_view.set_model(model)
+
+ col = gtk.TreeViewColumn()
+
+ # boolean
+ renderer = gtk.CellRendererToggle()
+ renderer.set_property('activatable',True)
+ renderer.connect("toggled", self.cb_toggle_clicked, tree_view, model)
+ col.pack_start(renderer, False)
+ col.set_title('Choose your ' + self.__media_type + ' folders')
+ col.set_alignment(0)
+ col.set_attributes(renderer, active=0)
+ tree_view.append_column(col)
+
+ # icon
+ renderer = gtk.CellRendererPixbuf()
+ col.pack_start(renderer, False)
+ col.set_attributes(renderer, pixbuf=1)
+ col.set_alignment(0)
+ tree_view.append_column(col)
+
+ # Text
+ renderer = gtk.CellRendererText()
+ renderer.set_property('xalign', 0)
+ col.pack_start(renderer, True)
+ col.set_attributes(renderer, markup=2)
+ col.set_alignment(0)
+ tree_view.append_column(col)
+ tree_view.connect("row-expanded", self.cb_row_expanded, model)
+ tree_view.connect("row-collapsed", self.cb_row_collapsed, model)
+
+ cancel_button = xml.get_widget('cancel_button')
+ commit_button = xml.get_widget('commit_button')
+
+ commit_button.connect('clicked', self.cb_commit_button)
+ cancel_button.connect('clicked', self.cb_cancel_button)
+
+ root = model.append(None, [False, icons.load_icon('folder-open') ,
+ '/ (root)', '/'])
+ self.cb_row_expanded(tree_view, root, '/', model)
+ tree_view.expand_row(0, False)
+
+
+ def cb_cancel_button(self, button):
+ """
+ Cancel the current modifications.
+
+ """
+ log.info('FileTree :: Cancel... Closing window...')
+ self.__window.hide()
+
+ def cb_commit_button(self, button):
+ """
+ Apply the current changes.
+
+ """
+ log.info('FileTree :: Commiting the new directories tree!')
+ conf = ''
+ for i in self.__selected_dirs:
+ if conf != '':
+ conf = conf + ';' + i
+ else:
+ conf = i
+
+
+ config.setValue('media_' + self.__media_type + '_paths', conf)
+ self.__window.hide()
+
+
+
+ def cb_toggle_clicked(self, renderer, path, tree_view, model):
+ """
+ Select the clicked toggle.
+
+ """
+ log.debug('FileTree :: Toggle clicked...')
+ log.debug('FileTree :: Renderer : ' + str(renderer))
+ log.debug('FileTree :: Path : ' + str(path))
+ log.debug('FileTree :: Model : ' + str(model))
+ iter = model.get_iter(path)
+ log.debug('FileTree :: Iter : ' + str(iter))
+ value = model.get_value(iter, 3)
+ log.debug('FileTree :: Value : ' + str(value))
+
+
+ if str(value) in self.__selected_dirs:
+ self.__selected_dirs.remove(str(value))
+ elif not str(value) in self.__path_nopermission:
+ self.__selected_dirs.append(str(value))
+
+ self.__mark_selected_items(tree_view, iter, path, model, True)
+
+
+ def cb_row_expanded(self, tree_view, iter, path, model):
+ """
+ Populate the list after the path `path`
+
+ """
+ log.debug('FileTree :: Self : ' + str(self))
+
+ log.debug('FileTree :: Value 0 : ' + str(model.get_value(iter, 0)))
+ log.debug('FileTree :: Value 1 : ' + str(model.get_value(iter, 1)))
+ log.debug('FileTree :: Value 2 : ' + str(model.get_value(iter, 2)))
+ fs_path = model.get_value(iter, 3)
+ log.debug('FileTree :: Value 3 : ' + str(fs_path))
+
+ self.__populate(tree_view, iter, path, model)
+ self.__mark_selected_items(tree_view, iter, path, model)
+
+ model.set_value(iter, 1, self.__get_icon(fs_path))
+
+
+ def __mark_selected_items(self, tree_view, iter, path, model, config_changed=False):
+ """
+ Mark all selected items.
+
+ """
+ selected_dirs = self.__selected_dirs
+
+ log.debug('FileTree :: Marking the item as select: ' + str(iter))
+ log.debug('FileTree :: Current selection: ' + str(selected_dirs))
+
+ iter = model.get_iter_root()
+
+ log.debug('FileTree :: Value : ' + str(model.get_value(iter, 3)))
+
+ ### Recursive folder scan.
+ self.__mark_nodes_recursive(tree_view, iter, model)
+
+
+ def __mark_nodes_recursive(self, tree_view, iter, model):
+ """
+ Mark all nodes after a selected path.
+
+ """
+ selected_dirs = self.__selected_dirs
+
+ count=model.iter_n_children(iter)
+ log.debug('FileTree :: Subdirs: ' + str(count) + ' [' +
+ str(model.get_value(iter, 2)) + ']')
+ j = count
+ while j >= 0:
+ child = model.iter_nth_child(iter, j)
+ if child != None:
+ fs_path = model.get_value(child, 3)
+ log.debug('FileTree :: Value: ' + fs_path +
+ ' is checked? is the path for a checked one?')
+
+ continue_checking = False
+
+ model.set_value(child, 0, False)
+
+ self.__clean_text(model, child, 2)
+
+ if fs_path in selected_dirs:
+ log.debug('FileTree :: Yeap. This folder' +
+ ' is selected.')
+ model.set_value(child, 0, True)
+ continue_checking = True
+ else:
+ log.debug('FileTree :: Nope. It\'s not selected')
+
+ if utils.is_path_to(selected_dirs, fs_path):
+ log.debug('FileTree :: Its path to someone else...')
+
+ text = model.get_value(child, 2)
+ model.set_value(child, 2, self.SELECTED_PATH_PANGO_STRING_START +
+ text +
+ self.SELECTED_PATH_PANGO_STRING_END)
+
+ continue_checking = True
+ else:
+ log.debug('FileTree :: Its not path... :(')
+
+ if utils.is_after_to(selected_dirs, fs_path) and not fs_path in self.__path_nopermission:
+ text = model.get_value(child, 2)
+
+ model.set_value(child, 2, self.INSIDE_SELECTED_PATH_PANGO_STRING_START +
+ text +
+ self.INSIDE_SELECTED_PATH_PANGO_STRING_END)
+
+ log.debug('FileTree :: Its after to someone else...')
+ model.set_value(child, 0, True)
+ continue_checking = True
+ else:
+ log.debug('FileTree :: Ok it\'s not more then one node.')
+
+ self.__mark_nodes_recursive(tree_view, child, model)
+
+ j = j - 1
+
+ def __clean_text(self, model, child, pos):
+ """
+ Clean the directories labels, removing the SELECT and
+ INSIDE_SELECTED marks. If its found it in the child
+ label.
+
+ """
+ text = model.get_value(child, pos)
+
+ if text.startswith(self.SELECTED_PATH_PANGO_STRING_START) and text.endswith(self.SELECTED_PATH_PANGO_STRING_END):
+
+ text = text[len(self.SELECTED_PATH_PANGO_STRING_START):
+ -len(self.SELECTED_PATH_PANGO_STRING_END)]
+
+ model.set_value(child, pos, text)
+
+ if text.startswith(self.INSIDE_SELECTED_PATH_PANGO_STRING_START) and text.endswith(self.INSIDE_SELECTED_PATH_PANGO_STRING_END):
+
+ text = text[len(self.INSIDE_SELECTED_PATH_PANGO_STRING_START):-len(self.INSIDE_SELECTED_PATH_PANGO_STRING_END)]
+
+ model.set_value(child, pos, text)
+
+
+ def __populate(self, tree_view, iter, path, model, recursive=False):
+ """
+ Populate the TreeView
+
+ """
+ log.debug('FileTree :: Poulating....')
+ log.debug('FileTree :: Tree view : ' + str(tree_view))
+ log.debug('FileTree :: Iter : ' + str(iter))
+ log.debug('FileTree :: Path : ' + str(path))
+ log.debug('FileTree :: Model : ' + str(model))
+
+ # FIXME: It's a ugly hack I know. It's working ant it's not that ugly for now :)
+ count=model.iter_n_children(iter)
+ log.debug('FileTree :: Subdirs: ' + str(count) + ' [' +
+ str(model.get_value(iter, 2)) + ']')
+ j = count
+
+ while j > 0 and count > 1:
+ child = model.iter_nth_child(iter, j)
+ log.debug('FileTree :: Removing : ' + str(iter) + '. Child: ' +
+ str(child) + ' (J: ' + str(j) +')')
+ if child != None:
+ model.remove(child)
+ j = j - 1
+
+ # lets populate the list now.
+ fs_path = model.get_value(iter, 3)
+ for subdir in self.get_subdirs(fs_path):
+ new_path = os.path.join(fs_path, subdir)
+ new_iter = model.append(iter, [False, self.__get_icon(new_path),
+ subdir, new_path])
+
+ if self.have_subdirs(new_path):
+ model.append(new_iter, [False, self.__get_icon(new_path),
+ 'Just one treeview record',
+ 'It\'s here just to say to you that exist a subdir' +
+ ' in this path'])
+
+ # This will remove the 'dummy' item inserted in all directories that heve sub-dirs.
+ child = model.iter_nth_child(iter, 0)
+ model.remove(child)
+
+ def __get_icon(self, path):
+ """
+ Get icon for the `path`
+
+ """
+ #FIXME: I want to know if i have permission to acess a folder or not,
+ # the have_subdirs method check for it and populate the
+ # self.__path_nopermission array if its not.
+
+ self.have_subdirs(path)
+
+ log.debug('FileTree :: Getting icon for: ' + path + '. ' +
+ str(self.__path_nopermission))
+
+ if path in self.__path_nopermission:
+ return icons.load_icon('folder-visiting')
+
+ try:
+ log.debug('FileTree :: Trying to load a custon folder icon: ' +
+ self.__path_custon_icon[path])
+ return icons.load_icon(self.__path_custon_icon[path])
+ except:
+ pass
+
+ return icons.load_icon('folder')
+
+
+ def have_subdirs(self, path):
+ """
+ Check if the `path` have one or more subdir.
+
+ """
+ log.debug('Checking if the path: ' + path + ' have one or more subdirectories')
+ if path == None:
+ return False
+
+ try:
+ for i in os.listdir(path):
+ if os.path.isdir(os.path.join(path, i)) == True:
+ return True
+ except OSError, a:
+ self.__path_nopermission.append(path)
+ log.debug('FileTree :: Sorry, i have no permission to look' +
+ ' inside: ' + str(path) + ' Detail: ' + str(a))
+ pass
+
+ return False
+
+ def get_subdirs(self, path, recursive=False):
+ """
+ Get subdirs in the `path`.
+
+ Recursive or not is an option, False is its
+ default value.
+
+ """
+ log.debug('FileTree :: Getting subirs of: ' + str(path))
+ dirs = []
+ if path == None:
+ return dirs
+
+ try:
+ for i in os.listdir(path):
+ if os.path.isdir(os.path.join(path, i)) == True:
+ dirs.append(i)
+ except:
+ pass
+
+ log.debug('FileTree :: Returning subdirs: ' + str(dirs))
+
+ return dirs
+
+ def cb_row_collapsed(self, tree_view, iter, path, model):
+ # FIXME: At this point, should remove the item from the list. Now its just using
+ # memmory unecessary.
+ model.set_value(iter, 1, self.__get_icon(model.get_value(iter, 3)))
+ log.debug('FileTree :: Ok collapsed')
+
+
+
More information about the Syncropated-commits
mailing list