[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