#!/usr/bin/env python
# -*- coding: UTF8 -*-

appName = 'Sniff'
appAuthors = ['Zack Cerza <zcerza@redhat.com>']

from dogtail import tree
import gobject
import gnome
program = gnome.program_init(appName, '0.1')
import gtk.glade
try:
	x = gtk.glade.XML('sniff.glade')
except RuntimeError:
	x = gtk.glade.XML('/usr/share/dogtail/glade/sniff.glade')
sniff = x.get_widget(appName)

view = x.get_widget('treeTreeView')

nameTextLabel = x.get_widget('nameTextLabel')
roleNameTextLabel = x.get_widget('roleNameTextLabel')
descTextLabel = x.get_widget('descTextLabel')
actionsTextLabel = x.get_widget('actionsTextLabel')
textLabel = x.get_widget('textLabel')
textTextView = x.get_widget('textTextView')

def quit(*args):
	gtk.main_quit()

def expandAll(widget, *args):
	global view
	if args[0] == True: view.expand_all()
	elif args[0] == False: view.collapse_all()

def showAbout(*args):
	about = gtk.AboutDialog()
	about.set_name(appName)
	about.set_authors(appAuthors)
	about.set_comments('Explore your desktop with Dogtail')
	about.set_license('GPL')
	about.set_website('http://no.site.yet/')
	about.show_all()

def connectSignals():
	sniff.connect('delete_event', quit)

	quit1 = x.get_widget('quit1')
	quit1.connect('activate', quit)

	expand_all1 = x.get_widget('expand_all1')
	expand_all1.connect('activate', expandAll, True)
	collapse_all1 = x.get_widget('collapse_all1')
	collapse_all1.connect('activate', expandAll, False)
	
	about1 = x.get_widget('about1')
	about1.connect('activate', showAbout)

	refreshMenuItem = x.get_widget('refresh1')
	refreshMenuItem.connect('activate', refreshAll)

	view.connect('button-press-event', buttonPress)
	view.connect('row-expanded', rowExpanded)
	view.connect('row-collapsed', rowCollapsed)

def buttonPress(widget, event, *userParams):
	global model
	try: path, treeViewCol, relX, relY = \
			view.get_path_at_pos(int(event.x), int(event.y))
	except TypeError: return
	node = model[path][0]
	setUpTable(node)

	if event.button == 3:
		menu = gtk.Menu()
		menuItem = None
		try:
			for action in node.actions:
				menuItem = gtk.MenuItem(action.name.capitalize())
				menuItem.connect('activate', menuItemActivate, action.do)
				menuItem.show()
				menu.append(menuItem)
		except AttributeError: pass
		if not menuItem: return
		menu.show()
		menu.popup(None, None, None, event.button, event.time)

# I hate globals too. I think we need one here, though.
# Make it a non-integer, so we can know if it has been set yet (later).
textTextViewBufferChangedLastHandlerID = 3.141592654

def setUpTable(node):
	"""Generic code for setting up the table under the TreeView"""
	nameTextLabel.set_text(node.name)
	roleNameTextLabel.set_text(node.roleName)
	descTextLabel.set_text(node.description)
	try:
		str = ''
		for action in node.actions: str = ' '.join([str, action.name]).strip()
		actionsTextLabel.set_text(str)
	except AttributeError: actionsTextLabel.set_text('')
	
	global textTextViewBufferChangedLastHandlerID
	# Have we connected this signal yet? If so, disconnect it before proceeding.
	if int(textTextViewBufferChangedLastHandlerID) == \
		textTextViewBufferChangedLastHandlerID: 
		textTextView.get_buffer().disconnect(textTextViewBufferChangedLastHandlerID)
	
	try:
		textTextView.set_sensitive(True)
		buffer = textTextView.get_buffer()
		buffer.set_text(node.text)
		try:
			# Eeew! I'm touching tree's privates.
			assert node._Node__editableText
			# Remember the handler ID of this connection.
			textTextViewBufferChangedLastHandlerID = \
				buffer.connect('changed', changeText, node)
		except AssertionError:
			textTextView.set_sensitive(False)
	except AttributeError:
		textTextView.get_buffer().set_text('')
		textTextView.set_sensitive(False)

def changeText(textBuffer, node):
	node.text = textBuffer.get_text(textBuffer.get_start_iter(), \
			textBuffer.get_end_iter())

def rowExpanded(treeview, iter, path, *userParams):
	global model
	row = model[path]
	childRows = row.iterchildren()
	node = row[0]
	try: 
		childNodes = node.children
		for childNode in childNodes:
			childRow = childRows.next()
			addChildren(childNode, childRow.iter)
	except AttributeError: pass

def rowCollapsed(treeview, iter, path, *userParams):
	global model
	row = model[path]
	childRows = row.iterchildren()
	try:
		while True:
			childRow = childRows.next()
			grandChildRows = childRow.iterchildren()
			try:
				while True:
					grandChildRow = grandChildRows.next()
					model.remove(grandChildRow.iter)
			except StopIteration: pass
	except StopIteration: pass

def menuItemActivate(menuItem, *userParams):
	method = userParams[0]
	if method: method()

def refreshAll(menuItem, *userParams):
	global model
	resetModel()

def populate(model, newChild, oldParent = None):
	import pdb
	#pdb.set_trace()
	iter = model.insert_before(oldParent, None)
	model.set_value(iter, 0, newChild)
	model.set_value(iter, 1, newChild.name)
	model.set_value(iter, 2, newChild.roleName)
	model.set_value(iter, 3, newChild.description)
	
	try: 
		for grandChild in newChild.children:
			populate(model, grandChild, iter)
	except AttributeError: pass

def addNodeToModel(node, parentInTreeView = None):
	global model
	iter = model.insert_before(parentInTreeView, None)
	model.set_value(iter, 0, node)
	return iter

def addChildren(node, parentInTreeView = None):
	global model
	try:
		for child in node.children:
			iter = addNodeToModel(child, parentInTreeView)
	except AttributeError: pass

def showNode(node, parentInTreeView = None):
	global model
	iter = addNodeToModel(node, parentInTreeView)
	addChildren(node, iter)

def resetModel():
	global model
	model.clear()
	showNode(tree.root)	

def getNodeAttr(column, cell, model, iter, attr):
	node = model.get_value(iter, 0)
	cell.set_property('text', getattr(node, attr))

def main():
	connectSignals()

	nameTextLabel.set_text('')
	roleNameTextLabel.set_text('')
	descTextLabel.set_text('')
	actionsTextLabel.set_text('')
	textTextView.set_sensitive(False)
	textTextView.get_buffer().set_text('')

	global sniff, view, model

	view.insert_column_with_data_func(-1, "Name", \
			gtk.CellRendererText(), getNodeAttr, 'name')
	view.insert_column_with_data_func(-1, "Role Name", \
			gtk.CellRendererText(), getNodeAttr, 'roleName')
	view.insert_column_with_data_func(-1, "Description", \
			gtk.CellRendererText(), getNodeAttr, 'description')
	for column in view.get_columns():
		column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
		column.set_resizable(True)
	view.show()
	sniff.show_all ()
	
	model = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, \
			gobject.TYPE_STRING, gobject.TYPE_STRING)
	view.set_model(model)

	resetModel()
	
	gtk.main()

if __name__ == '__main__': main()

