#! /usr/bin/python
#-*- coding: utf-8 -*-
# Murmur - a PyGTK2 client for museek 
# Code fragments taken from mucous, musetup-gtk, and nicotine
#
# daelstorm (C) 2005-2006
#
# 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 sys

win32 = sys.platform.startswith("win")
if win32:
     # Fetchs gtk2 path from registry
     try: import dbhash
     except: print _("Warning: the Berkeley DB module, dbhash, could not be loaded.")
     import _winreg
     import msvcrt
     try:
       k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\GTK\\2.0")
     except EnvironmentError:
       print _("You must install the Gtk+ 2.2 Runtime Environment to run this program")
       while not msvcrt.kbhit():
        pass
       sys.exit(1)
     else:    
      gtkdir = _winreg.QueryValueEx(k, "Path")
      import os
      os.environ['PATH'] += ";%s/lib;%s/bin" % (gtkdir[0], gtkdir[0])
#import gtk,
if win32:
	try:
		import gtk
	except:
		import pygtk
else:
	import pygtk
	pygtk.require("2.0")
import gtk
import gobject
import sys, os
import threading
import traceback
from threading import Thread

import gc
#gc.set_debug(gc.DEBUG_LEAK)
try:
	from Crypto.Hash import SHA256
	
except ImportError:	
	
	try:
		import mucipher
	except ImportError:
		print "WARNING: The Mucipher Module for Python wasn't found and neither was PyCrypto. One of these encryption modules is necessary to allow Murmur to connect to the Museek Daemon.\nDownload mucipher here: http://thegraveyard.org/files/pymucipher-0.0.1.tar.gz\nExtract the tarball, and as Root or sudo, run:\npython setup.py install\nYou'll need GCC, Python and SWIG.\nOr download PyCrypto from here: http://www.amk.ca/python/code/crypto.html"
		sys.exit()
try:
	import messages, driver
except ImportError:
	try:
		from museek import messages, driver
	except ImportError:
		print "WARNING: The Museek Message-Parsing modules, messages.py and/or driver.py  were not found. Please install them into your '/usr/lib/python2.X/site-packages/museek' directory, or place them in a 'museek' subdirectory of the directory that contains the murmur python scipt."
		sys.exit()

trayicon_load = 1
try:
	from pymurmur import trayicon
except:
	print "Optional TrayIcon module not found. Please build it if you want the TrayIcon to work."
	trayicon_load = 0
try:
	from pymurmur import imagedata
	from pymurmur.settings import Settings
except ImportError, e:
	print "Failed loading imagedata", e
	os._exit(1)
try:
	from pymurmur.utils import *
	from pymurmur.utils import _
	from pymurmur import utils
except ImportError, e:
	print "Failed loading pymurmur utils", e 
	os._exit(1)
from pymurmur.muscan import Muscan
	
from pymurmur.entrydialog import *

from time import sleep

import select, string, re, ConfigParser, getopt, shutil, commands
try:
	import pwd
except ImportError:
	print "Python module 'pwd' could not be loaded."
import threading, time
import signal
import tempfile
import imghdr

	
pid = os.getpid()

geoip_fail=0
try:
	import GeoIP
	gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
except ImportError:
	print "Python module 'pwd' could not be loaded."
	geoip_fail=1

config_dir = str(os.path.expanduser("~/.murmur/"))
log_dir = str(os.path.expanduser("~/.murmur/logs/"))
config_file = config_dir+"config"

DEBUG = False

def usage():
	print ("""Murmur is a PyGTK2 client for Museek, the P2P Soulseek Daemon
Dir: Daelstorm
Credit: Hyriand 
Version: %s
	Default options: none
	-c,	--config <file>	Use a different config file
	-l,	--log <dir>	Use a different logging directory
	-v,	--version	Display version and quit
	-d				Debug mode

	-h,	--help		Display this help and exit
	""" %version)
	sys.exit(2)
	
try:
	opts, args = getopt.getopt(sys.argv[1:], "hc:vl:d", ["help", "config=", "version", "log="])
except getopt.GetoptError:
	usage()
	sys.exit(2)
for opts, args in opts:
	if opts in ("-h", "--help"):
		usage()
		sys.exit()
	if opts in ("-c", "--config"):
		config_file=str(os.path.expanduser(args))
	if opts in ("-l", "--log"):
		log_dir=str(os.path.expanduser(args))
	if opts in ("-d"):
		DEBUG = True
	if opts in ("-v", "--version"):
		print "Murmur version: %s" % version
		sys.exit(2)

#parser = ConfigParser.ConfigParser()


## Modify and read the Murmur Config
#
class ConfigManager:
	## Constructor
	# @param self ConfigManager
	# @param murmur Murmur (Class)
	def __init__(self, murmur):
		## @var parser
		# ConfigParser instance
		
		self.parser = ConfigParser.ConfigParser()
		## @var murmur
		# Murmur (class)
		self.murmur = murmur
		
	## Create config dict from config file
	# @param self ConfigManager
	def create_config(self):
	
		self.parser.read([config_file])
	
		murmur_config_file = file(config_file, 'w')
		
		for i in self.murmur.Config.keys():
			if not self.parser.has_section(i):
				self.parser.add_section(i)
			for j in self.murmur.Config[i].keys():
				if j not in ["nonexisting", "hated", "options"]:
					self.parser.set(i,j, self.murmur.Config[i][j])
				else:
					self.parser.remove_option(i,j)
		self.parser.write(murmur_config_file)
		murmur_config_file.close()	
	
	## Create config file and parse options
	# @param self ConfigManager
	def read_config(self):
		
		self.parser.read([config_file])
		for i in self.parser.sections():
			for j in self.parser.options(i):
				val = self.parser.get(i,j, raw = 1)
	
				if j in ['login','passw','interface', 'trayapp', 'roombox', 'tickers_enabled', "ticker_cycle", 'default_room', "autobuddy", 'tooltips', "now-playing", "log_dir", "logcollapsed", "configfile", "now-playing-prefix", "browse_display_mode", "url reader", "url custom prefix", "url custom suffix", "transbox"] or i == "colors":
					if val != "None":
						self.murmur.Config[i][j] = val
				elif i == 'aliases':
					if val != "None":
						self.murmur.Config[i][j] = val
				else:
					try:
						self.murmur.Config[i][j] = eval(val, {})
					except:
						self.murmur.Config[i][j] = None
	
	## Write config file to disk
	# @param self ConfigManager
	def update_config(self):
		murmur_config_file = file(config_file, 'w')
		for i in self.murmur.Config.keys():
			if not self.parser.has_section(i):
				self.parser.add_section(i)
			for j in self.murmur.Config[i].keys():
				if j not in ["somethingwrong"]:
					self.parser.set(i,j, self.murmur.Config[i][j])
				else:
					self.parser.remove_option(i,j)
		self.parser.write(murmur_config_file)
		murmur_config_file.close()
	
	## Check the filesystem for the existance of the config file
	# Create it if it doesn't exist
	# Read it if it does exist 
	# @param self ConfigManager
	def check_path(self):
		if os.path.exists(config_dir):
			if os.path.exists(config_file) and os.stat(config_file)[6] > 0:
				self.read_config()
			else:
				self.create_config()
				
		else:
			os.mkdir(config_dir, 0700)
			create_config()
			

	
	
class ImageDialog( gtk.Dialog):
    def __init__(self, Mapp, title="Image", message="", picture=None, modal= True):
        gtk.Dialog.__init__(self)
        self.connect("destroy", self.quit)
        self.connect("delete_event", self.quit)
	if modal:
            self.set_modal(True)
	    
	box = gtk.VBox(spacing=10)
        box.set_border_width(10)
        self.vbox.pack_start(box)
        box.show()
	if message:
            label = gtk.Label()
	    label.set_markup(message)
	    label.set_line_wrap(True)
            box.pack_start(label)
            label.show()
	if picture is not None and picture != "":
		#pixbufanim2 = gtk.gdk.PixbufAnimation("%s"% picture)
		image1 = gtk.Image()
		image1.set_from_pixbuf(picture)
		image1.show()
		box.pack_start(image1)
	button = gtk.Button("Okay", stock="gtk-ok")
        button.connect("clicked", self.click)
        button.set_flags(gtk.CAN_DEFAULT)
        self.action_area.pack_start(button)
        button.show()
        button.grab_default()
        self.ret = None
	
    def quit(self, w=None, event=None):
        self.hide()
        self.destroy()
        gtk.main_quit()
	
    def click(self, button):
        self.ret = None
        self.quit()



class Networking(driver.Driver, Thread):
	def __init__(self, xapp):
		driver.Driver.__init__(self)
		Thread.__init__(self)
		self.frame = self.app=xapp
		self.config = {}
		self.invalidpass = 0
		self.socket = None

	## Ping
	def cb_ping(self):
		if DEBUG == True: print " **** cb_ping"
		
	def cb_server_privileges(self, time_left):
		if DEBUG == True: print " **** cb_server_privileges: %i" % time_left
		
	def cb_config_set(self, domain, key, value):
		gtk.gdk.threads_enter()
		try:
			if key in self.config[domain].keys():
				if DEBUG == True: print "Modified <"+key+"> in <" +domain+"> to <"+value + ">"
				self.config[domain][key] = value
				if domain == "banned":
					self.frame.userlists.banned.update(key, value)
				elif domain == "buddies":
					self.frame.userlists.buddies.update(key, value)
				elif domain == "ignored":
					self.frame.userlists.ignored.update(key, value)
				elif domain == "trusted":
					self.frame.userlists.trusted.update(key, value)
				if domain in ("banned", "buddies", "ignored", "trusted"):
					self.frame.ChatRooms.GetListStatus( key)
					self.frame.userlists.updateListIcon(key)
				
					
			else:
				if value == '':
					if DEBUG == True: print "Added <"+key+"> to <" +domain+">"
				else:
					if DEBUG == True: print "Added <"+key+"> to <" +domain+"> and set to <"+value+">"
				
				self.config[domain][key] = value
				if domain == "banned":
					self.frame.userlists.banned.append(key, value)
				elif domain in "buddies":
					self.frame.userlists.buddies.append(key, value)
				elif domain in "ignored":
					self.frame.userlists.ignored.append(key, value)
				elif domain in "trusted":
					self.frame.userlists.trusted.append(key, value)
				if domain in ("banned", "buddies", "ignored", "trusted"):
					self.frame.ChatRooms.GetListStatus( key)
					self.frame.userlists.updateListIcon(key)
					
			if domain == "interests.hate":
				self.frame.Recommendations.AddedHatedInterest(key)
			elif domain == "interests.like":
				self.frame.Recommendations.AddedLikedInterest(key)
				
		except Exception,e:
			if DEBUG == True: print " **** cb_config_set ERROR", e

		gtk.gdk.threads_leave()

	## Delete keys from self.config
	def cb_config_remove(self, domain, key):
		gtk.gdk.threads_enter()
		
		if key in self.config[domain].keys():
			if DEBUG == True: print "Removed <"+key+"> from <" +domain+">"
			if domain == "banned":
				self.frame.userlists.banned.remove(key)
			elif domain in "buddies":
				self.frame.userlists.buddies.remove(key)
			elif domain in "ignored":
				self.frame.userlists.ignored.remove(key)
			elif domain in "trusted":
				self.frame.userlists.trusted.remove(key)
			if domain in ("banned", "buddies", "ignored", "trusted"):
				self.frame.ChatRooms.GetListStatus(key)
				self.frame.userlists.updateListIcon(key)
			if domain == "interests.hate":
				self.frame.Recommendations.RemovedHatedInterest(key)
			elif domain == "interests.like":
				self.frame.Recommendations.RemovedLikedInterest(key)
			del self.config[domain][key]
		gtk.gdk.threads_leave()
		#self.display_config_update(domain)
	
	## Copy config to self.config at connection
	def cb_config_state(self, config):
		gtk.gdk.threads_enter()
		
		self.config = config.copy()
		if self.config.keys() != []:
			if "buddies" in self.config.keys():
				for user, comment in self.config["buddies"].items():
					self.frame.userlists.buddies.append(user, comment)
			else:
				self.ConfigSet("buddies", "", "")
			
			if "banned" in self.config.keys():
				for user, comment in self.config["banned"].items():
					self.frame.userlists.banned.append(user, comment)
					if not self.frame.user_stats.has_key(user):
						self.PeerStats(user)
						self.PeerStatus(user)
			else:
				self.ConfigSet("banned", "", "")
			
			if "ignored" in self.config.keys():
				for user, comment in self.config["ignored"].items():
					self.frame.userlists.ignored.append(user, comment)
					if not self.frame.user_stats.has_key(user):
						self.PeerStats(user)
						self.PeerStatus(user)
			else:
				self.ConfigSet("ignored", "", "")
				
			if "trusted" in self.config.keys():
				for user, comment in self.config["trusted"].items():
					self.frame.userlists.trusted.append(user, comment)
			else:
				self.ConfigSet("trusted", "", "")
			if self.config.has_key("interests.like"):
				for interest in self.config["interests.like"].keys():
					self.frame.Recommendations.AddedLikedInterest(interest)
			if self.config.has_key("interests.hate"):
				for interest in self.config["interests.hate"].keys():
					self.frame.Recommendations.AddedHatedInterest(interest)
		self.frame.Muscan.GetConfig()
		gtk.gdk.threads_leave()
				
	## Add new/replace old keys to self.config
	def mod_config(self, changetype, username, value=''):
		#print changetype, username, value
		if changetype == "buddy":
			if username not in self.config["buddies"].keys():
				self.ConfigSet("buddies", username, value)
				if not self.frame.user_stats.has_key(username):
					self.PeerExists(username)
		elif changetype == "unbuddy":
			if username in self.config["buddies"].keys():
				self.ConfigRemove("buddies", username)
			#else:
				#if DEBUG == True: print "User not in buddy list: %s" % username
		elif changetype == "trust":
			if username not in self.config["trusted"].keys():
				self.ConfigSet("trusted", username, value)
				if not self.frame.user_stats.has_key(username):
					self.PeerExists(username)
		elif changetype == "distrust":
			if username in self.config["trusted"].keys():
				self.ConfigRemove("trusted", username)
			#else:
				#if DEBUG == True: print "User not in trusted list: %s" % username
		elif changetype == "ban":
			if username not in self.config["banned"].keys():
				self.ConfigSet("banned", username, value)
				if not self.frame.user_stats.has_key(username):
					self.PeerExists(username)
		elif changetype == "unban":
			if username in self.config["banned"].keys():
				self.ConfigRemove("banned", username)
			#else:
				#if DEBUG == True: print "User not in ban list: %s" % username
		elif changetype == "ignore":
			if username not in self.config["ignored"].keys():
				self.ConfigSet("ignored", username, value)
				#if DEBUG == True: print "Ignored: %s" % username
				if not self.frame.user_stats.has_key(username):
					self.PeerExists(username)
		elif changetype == "unignore":
			if username in self.config["ignored"].keys():
				self.ConfigRemove("ignored", username)
			#else:
				#if DEBUG == True: print "User not in ignore list: %s" % username
		elif changetype == "autojoin":
			room = username
			if room not in self.config["autojoin"].keys():
				self.ConfigSet("autojoin", room, "")
			#else:
				#if DEBUG == True: print "Room already autojoined: %s" % room

		elif changetype == "unautojoin":
			room = username
			if room in self.config["autojoin"].keys():
				self.ConfigRemove("autojoin", room)
			#else:
				#if DEBUG == True: print "Room not autojoined: %s" % room
		elif changetype == "autojoin":
			room = username
			if room not in self.config["autojoin"].keys():
				self.ConfigSet("autojoin", room, "")
			#else:
				#if DEBUG == True: "Room already autojoined: %s" % room

		elif changetype == "unautojoin":
			room = username
			if room in self.config["autojoin"].keys():
				self.ConfigRemove("autojoin", room)
			#else:
				#if DEBUG == True:  "Room not autojoined: %s" % room
				
	def Send(self, message):
		if self.frame.Networking.connected == False:
			return
		try:
			self.send( message ) 
		except Exception, e:
			if DEBUG == True: print "Sending message failed", message, e
	## Got Global Recommendations
	# @param self Networking (Driver Class)
	# @param recommendations list of recommendations [item, number of recommends] 
	def cb_get_global_recommendations(self, recommendations):
		try:
			#self.frame.Recommendations.data["recommendations"] = self.frame.SortedDict()
			self.frame.Recommendations.UpdateRecommendations(recommendations)
			#for rec, num in recommendations.items():
				#self.frame.Recommendations.data["recommendations"] [rec] = num
			#if self.frame.mode == "lists" and self.frame.UsersLists.current == "interests":
				#self.frame.Recommendations.DrawInterests()
		except Exception, e:
			print "CB Get Global Recommendations" + str(e)
	
	## Got Similar Users list
	# @param self Networking (Driver Class)
	# @param users List of format [username, status=(0,1,2)]
	def cb_get_similar_users(self, users):
		try:
			
			#self.frame.Recommendations.data["similar_users"] = self.frame.SortedDict()
			self.frame.Recommendations.UpdateSimilarUsers(users)
			#for rec, num in users.items():
				#self.frame.Recommendations.data["similar_users"][rec] = num
			##if self.frame.mode == "lists" and self.frame.UsersLists.current == "interests":
				#self.frame.Recommendations.DrawInterests()
		except Exception, e:
			print "CB Similar Users" + str(e)
			self.frame.PrintTraceBack()
	
	## Got Personal Recommendations
	# @param self Networking (Driver Class)
	# @param recommendations list of recommendations [item, number of recommends]
	def cb_get_recommendations(self, recommendations):
		try:
			#self.frame.Recommendations.data["recommendations"] = self.frame.SortedDict()
			self.frame.Recommendations.UpdateRecommendations(recommendations)
			#for rec, num in recommendations.items():
				#self.frame.Recommendations.data["recommendations"] [rec] = num
			#if self.frame.mode == "lists" and self.frame.UsersLists.current == "interests":
				#self.frame.Recommendations.DrawInterests()
		except Exception, e:
			print "CB Get  Recommendations" + str(e)
	
	## Got Similar Users list for an Item
	# @param self Networking (Driver Class)
	# @param item string
	# @param users List of format [username, status=(0,1,2)]
	def cb_get_item_similar_users(self, item, users):
		try:
			#self.frame.Recommendations.data["similar_users"] = self.frame.SortedDict()
			self.frame.Recommendations.UpdateSimilarUsers(users)
			#for rec, num in users.items():
				#self.frame.Recommendations.data["similar_users"][rec] = num
			#if self.frame.mode == "lists" and self.frame.UsersLists.current == "interests":
				#self.frame.Recommendations.DrawInterests()
		except Exception, e:
			print "CB Item Similar Users" + str(e)
	
	## Got Recommendations for an Item
	# @param self Networking (Driver Class)
	# @param item string
	# @param recommendations list of recommendations [item, number of recommends]
	def cb_get_item_recommendations(self, item, recommendations):
		try:
			self.frame.Recommendations.UpdateRecommendations(recommendations)
			#self.frame.Recommendations.data["recommendations"] = self.frame.SortedDict()
			#for rec, num in recommendations.items():
				#self.frame.Recommendations.data["recommendations"] [rec] = num
			#if self.frame.mode == "lists" and self.frame.UsersLists.current == "interests":
				#self.frame.Recommendations.DrawInterests()
		except Exception, e:
			print "CB Get Item Recommendations" + str(e)

        def cb_room_list(self, roomlist):
		gtk.gdk.threads_enter()

		if DEBUG == True: print " **** cb_room_list", len(roomlist)
		#self.frame.room_lists = {}
		#for x, y in roomlist.items():
			#self.chatrooms.rooms[x] = y
			##print x, y
			
		self.frame.ChatRooms.UpdateRoomList(roomlist)
		gtk.gdk.threads_leave()

	def cb_room_tickers(self, room, tickers):
		if DEBUG == True: print " **** cb_room_ticker"
		gtk.gdk.threads_enter()
		gtk.gdk.threads_leave()

	def cb_room_ticker_set(self, room, user, message):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_room_ticker_set"
		gtk.gdk.threads_leave()

	def cb_search_ticket(self, query, ticket):
		gtk.gdk.threads_enter()
		
		if DEBUG == True: print " **** cb_search_ticket", query, ticket
		self.frame.Searches.NewSearch( query, ticket)
		
		gtk.gdk.threads_leave()


	def cb_search_results(self, ticket, user, free, speed, queue, results):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_search_results"

		self.frame.Searches.NewResults(ticket, user, free, speed, queue, results)
		gtk.gdk.threads_leave()



	def cb_transfer_state(self, downloads, uploads):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_transfer_state"
		for transfer in uploads:
			self.frame.uploads.append(user=transfer.user, filename=None, rate=transfer.rate, state=transfer.state, filepos=transfer.filepos, filesize=transfer.filesize, path=transfer.path, error=transfer.error, place=transfer.place)
		for transfer in downloads:
			self.frame.downloads.append(user=transfer.user, filename=None, rate=transfer.rate, state=transfer.state, filepos=transfer.filepos, filesize=transfer.filesize, path=transfer.path, error=transfer.error, place=transfer.place)

		gtk.gdk.threads_leave()


	def cb_transfer_update(self, transfer):
		gtk.gdk.threads_enter()
		try:
			if DEBUG == True: print " **** cb_transfer_update"
			if transfer.is_upload:
				self.frame.uploads.update(user=transfer.user, filename=None, rate=transfer.rate, state=transfer.state, filepos=transfer.filepos, filesize=transfer.filesize, path=transfer.path, error=transfer.error, place=transfer.place)
			else:
				self.frame.downloads.update(user=transfer.user, filename=None, rate=transfer.rate, state=transfer.state, filepos=transfer.filepos, filesize=transfer.filesize, path=transfer.path, error=transfer.error, place=transfer.place)
		except Exception,e:
			if DEBUG == True: print " **** cb_transfer_update ERROR", e
		gtk.gdk.threads_leave()
			
	def cb_transfer_remove(self, transfer):
		gtk.gdk.threads_enter()
		
		if DEBUG == True: print " **** cb_transfer_remove"
		user_path = transfer[1], transfer[2]
		if transfer[0]:
			self.frame.uploads.remove(transfer)
		else:
			self.frame.downloads.remove(transfer)
		gtk.gdk.threads_leave()
		
	def cb_user_shares(self, user, shares):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_user_shares"
		#self.frame.get_shares(user, shares)
		try:
			self.frame.userbrowses.GotUserBrowse(user, shares)
		except Exception,e:
			if DEBUG == True: print " **** cb_user_shares ERROR", e
		gtk.gdk.threads_leave()
			
	def cb_user_info(self, user, info, picture, uploads, queue, slotsfree):
		gtk.gdk.threads_enter()
		try:
			if DEBUG == True:
				print "got %s's userinfo" % user

			self.frame.userinfos.GotUserInfo(user, info, picture, uploads, queue, slotsfree)
	
		except Exception,e:
			if DEBUG == True: print " **** cb_user_info ERROR", e
		gtk.gdk.threads_leave()
		
	def cb_room_said(self, room, user, text):
		gtk.gdk.threads_enter()
		try:
			self.frame.ChatRooms.SayChatRoom(room, user, text)
			self.frame.Logging.ChatRoomLog(room, user, text)
		except Exception,e:
			if DEBUG == True: print " **** cb_room_said ERROR", e		
		gtk.gdk.threads_leave()
			
	def cb_room_state(self, roomlist, joined, tickers):
		gtk.gdk.threads_enter()
		if DEBUG == True: print "Logged in, getting Rooms"
		try:
		
			self.frame.ChatRooms.UpdateRoomList(roomlist)
			joined_rooms = joined.keys()
			joined_rooms.sort(key=str.lower)
			for room in joined_rooms:
				for users, stats in joined[room].items():
					self.frame.user_stats[users] = [stats[0], stats[1], stats[2], stats[3], stats[4], 1]
				self.frame.ChatRooms.JoinRoom(str(room), joined[room])

		except Exception, e:
			if DEBUG == True: print "Room State bug", e
			self.frame.PrintTraceBack()

		gtk.gdk.threads_leave()
		
	def cb_room_joined(self, room, list_of_users):
		gtk.gdk.threads_enter()
		if DEBUG == True:
			print "Joined room: %s" % room
		try:
			
	
			self.frame.ChatRooms.JoinRoom(room, list_of_users)
				
				
		except Exception, e:
			if DEBUG == True: print "Join room bug", e
		gtk.gdk.threads_leave()
		
	def cb_room_left(self, room):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_room_left %s"% room
		try:
			self.frame.ChatRooms.LeaveRoom(room)
		except Exception, e:
			if DEBUG == True: print "Leave room bug", e
		gtk.gdk.threads_leave()
			
	def cb_room_user_joined(self, room, user, stats):
		gtk.gdk.threads_enter()
		try:
			if DEBUG == True:
				print "%s joined room \'%s\' " %( user, room)

			#self.frame.rooms[room][user] = stats
			self.frame.user_stats[user] = [stats[0], stats[1], stats[2 ], stats[3], stats[4], 1] 
			
			self.frame.ChatRooms.UserJoinedRoom(room, user)
			
		except Exception, e:
			if DEBUG == True: print "User Joined room bug", e
		gtk.gdk.threads_leave()

	
	def cb_room_user_left(self, room, user):
		gtk.gdk.threads_enter()
		try:
			if DEBUG == True:
				print "%s left room %s" % (user, room)
				
			self.frame.ChatRooms.UserLeftRoom(room, user)


		except Exception, e:
			if DEBUG == True: print "User Left room bug", e
		gtk.gdk.threads_leave()

	def cb_private_message(self, direction, timestamp, user, message):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_private_message"
		if DEBUG == True: print direction, timestamp, user, message
		try:
			
			if DEBUG == True:
				print "%s PM'd to you: %s" % (user, message)

			self.frame.PrivateChats.ShowMessage(direction, user, message)
		except Exception,e:
			if DEBUG == True: print " **** cb_private_message ERROR", e
		gtk.gdk.threads_leave()
			
	def cb_peer_address(self, user, ip, port):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_peer_address"
		try:
			if user in self.frame.ip_requested:
				self.frame.ip_requested.remove(user)
				if geoip_fail==0:
					country =  gi.country_name_by_addr( str(ip) )
					message="%s's IP: %s Port: %s Country: %s"  % (user, str(ip), str(port), country)
					#s= self.frame.display_box(title="IP Address", message = message  )
					self.frame.AppendToLogWindow(message)
					if DEBUG == True: print message
				else:
					if DEBUG == True: print "No Geoip"
					message="%s's IP: %s Port: %s" % (user, str(ip), str(port) )
					self.frame.AppendToLogWindow(message)
		except Exception,e:
			if DEBUG == True: print " **** cb_peer_address ERROR", e
		gtk.gdk.threads_leave()
			
	def cb_login_error(self, reason):
		gtk.gdk.threads_enter()
		try:
			if reason == "INVPASS":
				self.invalidpass = 1
				if DEBUG == True:
					print "Invalid Password"
				
				self.frame.TrayApp.SetToolTip( "Couldn't connect to Museek: %s" % "Invalid Password")
				self.frame.update_statusbar( "Invalid Password")
	
				
			else:
				self.invalidpass = 0
				if DEBUG == True:
					print "couldn't log in: " + reason
				
				self.frame.update_statusbar( "Couldn't Login")
				
			self.frame.TrayApp.SetImage("red")
		except Exception,e:
			if DEBUG == True: print " **** cb_login_error ERROR", e
		self.connected = False
		gtk.gdk.threads_leave()

	def cb_login_ok(self):
		
		try:
			self.invalidpass = 0
			if DEBUG == True:
				print "Logging in..."
		except Exception,e:
			if DEBUG == True: print " **** cb_login_ok ERROR", e
		self.connected = True
		
	def disconnect(self, string):
		
		try:
			if self.frame.username != None:
				#self.timer.cancel()
				driver.Driver.close(self)
				#self.close()
				self.connected = False
				self.config = {}
				self.invalidpass = 0
				self.frame.downloads.Clear()
				self.frame.uploads.Clear()
	

		except Exception,e:
			if DEBUG == True: print "disconnect ERROR", e
		
	def cb_disconnected(self):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_disconnected"
		try:
			
			self.frame.TrayApp.SetImage("red")

			self.frame.TrayApp.SetToolTip( "Disconnected from Museek")
			
			self.frame.update_statusbar( "Disconnected from Museek")
			
			self.frame.username =None
			self.frame.status = 2
			self.config = {}

			self.frame.ChatRooms.ConnClose()

			self.connected = False
		except Exception, e:
			if DEBUG == True: print " **** cb_disconnected ERROR", e
		gtk.gdk.threads_leave()
		
	def cb_server_state(self, state, username):
		gtk.gdk.threads_enter()
		try:
			
			if state != self.frame.status:
				if DEBUG == True:
					print  str(state), username
			
				self.frame.status = state
				if self.frame.status:
					message = "Connected to Museek: %s Status: Away" % username
					
					self.frame.TrayApp.SetToolTip( message)
					self.frame.update_statusbar( message)
					self.frame.TrayApp.SetImage("yellow")
					
				elif self.frame.status  == 2:
					message = "Connected to Museek: %s Status: Online" % username
					
					self.frame.TrayApp.SetToolTip( message )
					self.frame.update_statusbar( message )
					self.frame.TrayApp.SetImage("green")
					
				else:
					self.frame.TrayApp.SetImage("red")

			self.frame.username = username
					
		except Exception,e:
			if DEBUG == True: print " **** cb_server_state ERROR", e
		gtk.gdk.threads_leave()
		
	def cb_server_status_set(self, status):
		gtk.gdk.threads_enter()
		if DEBUG == True: print " **** cb_server_status_set ", status
		try:
			
			if status != self.frame.status:
				self.frame.status = status
				if self.frame.status:
					message = "Connected to Museek: %s Status: Away" % self.frame.username
					self.frame.TrayApp.SetToolTip( message)
					self.frame.update_statusbar( message)
					self.frame.TrayApp.SetImage("yellow")
				else:
					message = "Connected to Museek: %s Status: Online" % self.frame.username
					self.frame.TrayApp.SetToolTip( message ) 
					self.frame.update_statusbar( message )
					self.frame.TrayApp.SetImage("green")
			
		except Exception,e:
			if DEBUG == True: print " **** cb_server_status_set ERROR", e
		gtk.gdk.threads_leave()
                
	def cb_peer_exists(self, user, exists):
		
		if DEBUG == True: print "%s exists? %i" % (user, exists)
		try:
			if user in self.frame.user_stats: 
				self.frame.user_stats[user][5] = exists
			else:
				self.frame.user_stats[user] = [0, 0, 0, 0, 0, exists]
		except Exception,e:
			if DEBUG == True: print " **** cb_peer_exists ERROR", e
		
                
	def cb_peer_stats(self, user, speed, downloads, files, dirs):
		if DEBUG == True: print " **** cb_peer_stats", user, speed, downloads, files, dirs

		try:
			if user in self.frame.user_stats:
				stats = self.frame.user_stats[user]
				#if stats[1] == speed and stats[2] == downloads and stats[3] == files and stats[4] == dirs:
					#print "same"
					#return
				self.frame.user_stats[user] = [stats[0], speed, downloads, files, dirs, stats[5]]
				
			else:
				self.frame.user_stats[user] = [0, speed, downloads, files, dirs, 1]
		except Exception,e:
			if DEBUG == True: print " **** cb_peer_stats ERROR", e
		#gtk.gdk.threads_enter()
		
		self.frame.ChatRooms.GetUserStats( user, speed, files)
		self.frame.userlists.updateStats(user, self.frame.user_stats[user])

		#gtk.gdk.threads_leave()	
			
	def cb_peer_status(self, user, status):
		if DEBUG == True: print " **** cb_peer_status", user, status
		try:
			if user in self.frame.user_stats:

				self.frame.user_stats[user][0] = status
				
	
			else:
				self.frame.user_stats[user] = [status, 0, 0, 0, 0, 1]
			
			## Update Lists with new status information
			self.frame.ChatRooms.GetUserStatus( user, status)
			self.frame.userlists.updateStatus(user, status)
			self.frame.PrivateChats.updateStatus(user, status)
			
		except Exception,e:
			if DEBUG == True: print " **** cb_peer_status ERROR1", e
			
	## Museekd sent us a special message
	#
	# @param self is the Networking class
	# @param type is a bool; False if the message relates to the Server / True for Peer
	# @param message is the message string
	def cb_status_message(self, type, message):
		gtk.gdk.threads_enter()
		try:
			if type == 1:
				stype = "Peer"
			elif type == 0:
				stype = "Server"
			
			self.frame.AppendToLogWindow( "%s Message: %s" % (stype, message))
			
		except Exception,e:
			print "cb_status_message: " +str( e)
		gtk.gdk.threads_leave()
			
	def connect_to_museekd(self, string):

		if self.frame.username != None:
			self.disconnect("")
		try:
			if self.invalidpass == 0:
				if self.frame.Config["connection"]["passw"] != None:
					#self.timer = threading.Timer(10.0, self.CheckNick)
					#self.timer.start()
					driver.Driver.connect(self, self.frame.Config["connection"]["interface"],  self.frame.Config["connection"]["passw"], messages.EM_CHAT |  messages.EM_USERINFO| messages.EM_PRIVATE | messages.EM_TRANSFERS  | messages.EM_USERSHARES | messages.EM_CONFIG |  messages.EM_INTERESTS)
					
					if DEBUG == True:
						print "connect attempt"

				else:
					raise Exception,  "NOPASS"
					
			else:
				raise Exception,  "INVPASS"
				

		except Exception, e:
			if DEBUG == True: 
				if "INVPASS" in e:
					print "Incorrect Password, try another."
					#self.SetToolTip( "Couldn't connect to Museek: %s" % "Invalid Password")
				elif  "NOPASS" in e:
					print "Set a Password."
					#self.SetToolTip( "Couldn't connect to Museek: %s" % "Set a Password")
				elif  "Connection refused" in e:
					print e[1] +", make sure the daemon is running, or change the interface."
					#self.SetToolTip( "Make sure Museek is running, or try a different Interface.")
				print "Connect to museekd Error: ", e
			self.connected = False

	## Process Socket Data
	def run(self):
		if DEBUG == True:  print self.frame.pid
		self.connected = True
		while 1:
		#if 1:
			try:
				d = 0
				#while self.frame.Config["connection"]["passw"]  == None or self.frame.Config["connection"]["passw"] == "None":
					#sleep(0.1)
				if self.socket != None:

					r, w, x = select.select([self.socket, sys.stdin], [], [self.socket], d)
					
					if self.socket in r:
						#try:
							#print r[0]
						#except:
							#pass
						driver.Driver.process(self)
				else:
					
					if self.connected == True:
						self.connect_to_museekd("")
					
				sleep(0.001)
				
				#self.frame.MurmurWindow.show_all() 

			except Exception, e:
				if DEBUG == True: print "Process Exception", Exception, e
			except e:
				if DEBUG == True: print e
		
	## Failsafe Sending of messages to Museekd
	# @param self Networking (class)
	# @param message messages instance
	def SendMessage(self, message):
		if self.frame.Networking.connected == False:
			return
		try:
			self.send(message)
		except Exception, e:
			print "SendMessage: " + str(e) + " " + str(message)
			
	## Abort transfer (remains in transfer list)
	# @param self Networking (class)
	# @param direction (1: upload, 0:download)
	# @param user username
	# @param path file to be transfered
	def TransferAbort(self, direction, user, path):
		## Transfer messages
		message = messages.TransferAbort(direction, user, path)
		self.SendMessage(message)
	
	## Remove transfer from transfer list
	# @param self Networking (class)
	# @param direction (1: upload, 0:download)
	# @param user username
	# @param path file to be transfered
	def TransferRemove(self, direction, user, path):
		message = messages.TransferRemove(direction, user, path)
		self.SendMessage(message)
	
	## Check place in queue
	# @param self Networking (class)
	# @param user username
	# @param path file in queue
	def TransferUpdate(self, user, path):
		message = messages.TransferUpdate(user, path)	
		self.SendMessage(message)
	
	## Download a file
	# @param self Networking (class)
	# @param user username
	# @param path file to be transfered
	def DownloadFile(self, user, path):
		message = messages.DownloadFile(user, path)
		self.SendMessage(message)
	## Download a file to a local directory
	# @param self Networking (class)
	# @param user username
	# @param path file to be transfered
	# @param directory local save directory
	def DownloadFileTo(self, user, path, directory):
		message = messages.DownloadFileTo(user, path, directory)
		self.SendMessage(message)
	## Ask user to send the contents of a directory
	# @param self Networking (class)
	# @param user username
	# @param directory Directory to recieve
	def GetFolderContents(self, user, directory):
		message = messages.GetFolderContents(user, directory)
		self.SendMessage(message)
	## Upload a file to user from path
	# @param self Networking (class)
	# @param user username
	# @param path file to be transfered	
	def UploadFile(self, user, path):
		message = messages.UploadFile(user, path) 
		self.SendMessage(message)
	## Say message in room
	# @param self Networking (class)
	# @param room Room
	# @param message text
	def SayRoom(self, room, message):
		messages.SayRoom(room, message) 
		self.SendMessage(message)
	## Leave a Room
	# @param self Networking (class)
	# @param room leave this room
	def LeaveRoom(self, room):
		message = messages.LeaveRoom(room) 
		self.SendMessage(message)
	## Get Room List
	# @param self Networking (class)
	def RoomList(self):
		message = messages.RoomList()
		self.SendMessage(message)
	## Say line in room
	# @param self Networking (class)
	# @param room A Room you are in
	# @param line message
	def SayRoom(self, room, line):
		message = messages.SayRoom(room, line) 
		self.SendMessage(message)
	## Set your ticker in room
	# @param self Networking (class)
	# @param room Room name
	# @param ticker message
	def RoomTickerSet(self, room, ticker):
		message = messages.RoomTickerSet(room, ticker)
		self.SendMessage(message)
	## Join a room
	# @param self Networking (class)
	# @param room Room name
	def JoinRoom(self, room):
		message = messages.JoinRoom(room)
		self.SendMessage(message)
	## Get a user's IP address and listen port
	# @param self Networking (class)
	# @param user Username
	def PeerAddress(self, user):
		message = messages.PeerAddress(user)
		self.SendMessage(message)
	
	## Private Chat messages
	# @param self Networking (class)
	# @param direction 1 if outgoing 0 if incoming
	# @param user username of user message is coming from or going to
	# @param line message
	def PrivateMessage(self, direction, user, line):
		message = messages.PrivateMessage(direction, user, line) 
		self.SendMessage(message)
		
	## Get a user's away status 
	# @param self Networking (class)
	# @param user username 
	def PeerStatus(self, user):
		message = messages.PeerStatus(user)
		self.SendMessage(message)
	## Does a user exist in the server's database? 
	# @param self Networking (class)
	# @param user username 
	def PeerExists(self, user):
		self.SendMessage(messages.PeerExists(user))
	## Get a user's statistics
	# @param self Networking (class)
	# @param user username
	def PeerStats(self, user):
		message = messages.PeerStats(user)
		self.SendMessage(message)
	## Get a user's userinfo
	# @param self Networking (class)
	# @param user username
	def UserInfo(self, user):
		message = messages.UserInfo(user)
		self.SendMessage(message)
	## Get a user's shares
	# @param self Networking (class)
	# @param user username
	def UserShares(self, user):
		message = messages.UserShares(user)
		self.SendMessage(message)
	## Search for a string in one of three methods
	# @param self Networking (class)
	# @param searchtype (0:Global, 1:Buddy, 2:Rooms)
	# @param query Search string
	def Search(self, searchtype, query, user=None):

		if searchtype in (0, 1, 2):
			message = messages.Search(searchtype, query )
			self.SendMessage(message)
		elif searchtype == 3 and user is not None:
			self.UserSearch(user, query)
			
	## Search a user's shares for a string
	# @param self Networking (class)
	# @param user Username
	# @param query Search string
	def UserSearch(self, user, query):
		message = messages.UserSearch(user, query )
		self.SendMessage(message)
	## Search via the Wishlist
	# @param self Networking (class)
	# @param query Search Query
	def WishListSearch(self, query):
		message = messages.WishListSearch(query )
		self.SendMessage(message)
	## Get a list of users with your interests
	# @param self Networking (class)
	def GetSimilarUsers(self):
		message = messages.GetSimilarUsers()
		self.SendMessage(message)
	## Get a list of recommendations related to your interests
	# @param self Networking (class)
	def GetRecommendations(self):
		message = messages.GetRecommendations()
		self.SendMessage(message)
	## Get a list of recommendations related based on popularity
	# @param self Networking (class)
	def GetGlobalRecommendations(self):
		message = messages.GetGlobalRecommendations()
		self.SendMessage(message)
	## Add A liked interest
	# @param self Networking (class)
	# @param interest string
	def AddInterest(self, interest):
		message = messages.AddInterest(interest)
		self.SendMessage(message)
	## Add a hated interest
	# @param self Networking (class)
	# @param interest string
	def AddHatedInterest(self, interest):
		message = messages.AddHatedInterest(interest)
		self.SendMessage(message)
	## Remove a liked interest
	# @param self Networking (class)
	# @param interest string
	def RemoveInterest(self, interest):
		message = messages.RemoveInterest(interest)
		self.SendMessage(message)
	## Remove a hated interest
	# @param self Networking (class)
	# @param interest string
	def RemoveHatedInterest(self, interest):
		message = messages.RemoveHatedInterest(interest)
		self.SendMessage(message)
	## Check the amount of time of server privileges we have left
	# @param self Networking (class)
	def CheckPrivileges(self):
		message = messages.CheckPrivileges()
		self.SendMessage(message)
	## Give a number of days of privileges ot a user (Must have privileges to give them)
	# @param self Networking (class)
	# @param user Username
	# @param days days of privileges
	def GivePrivileges(self, user, days):
		message = messages.GivePrivileges(user, days)
		self.SendMessage(message)
		
	## Set your away status
	# @param self Networking (class)
	# @param status (1:away, 0:online)
	def SetStatus(self, status):
		message = messages.SetStatus(status)
		self.SendMessage(message)
		
	## Museekd connect to server (Reconnect if connected)
	# @param self Networking (class)
	def ConnectServer(self):
		message = messages.ConnectServer()
		self.SendMessage(message)
	## Museekd disconnect from server
	# @param self Networking (class)
	def DisconnectServer(self):
		message = messages.DisconnectServer()
		self.SendMessage(message)
	## Museekd reload the shares db from disk
	# @param self Networking (class)	
	def ReloadShares(self):
		message = messages.ReloadShares()
		self.SendMessage(message)
	## Set an option in Museekd's config
	# @param self Networking (class)
	# @param domain parent of key
	# @param key key being changed
	# @param value value of key
	def ConfigSet(self, domain, key, value):
		message = messages.ConfigSet(domain, key, value)
		self.SendMessage(message)
	## Remove an option from Museekd's config
	# @param self Networking (class)
	# @param domain parent of key
	# @param key key being changed
	def ConfigRemove(self, domain, key):
		message = messages.ConfigRemove(domain, key)
		self.SendMessage(message)
	## Ping Museekd
	# @param self Networking (class)
	# @param num number that will be echoed back to us
	def Ping(self, num):
		message = messages.Ping(num)
		self.SendMessage(message)



class PopupMenu(gtk.Menu):
	def __init__(self, frame, type):
		gtk.Menu.__init__(self)
		self.frame = frame
		self.type = type
		self.user = None
		self.directory = None
		self.path = None
		self.file = None
		
	def setup(self, *items):
		for item in items:
			if item[0] == "":
				menuitem = gtk.MenuItem()
			elif item[0] == 1:
				menuitem = gtk.MenuItem(item[1])
				menuitem.set_submenu(item[2])
				if item[3] is not None:
					menuitem.connect("activate", item[3])
			else:
				if item[0][0] == "$":
					menuitem = gtk.CheckMenuItem(item[0][1:])
				elif item[0][0] == "#":
					menuitem = gtk.ImageMenuItem(item[0][1:])
					img = gtk.image_new_from_stock(item[2], gtk.ICON_SIZE_MENU)
        				menuitem.set_image(img)
				elif item[0][0] == "%":
					menuitem = gtk.ImageMenuItem(item[0][1:])	
					img = gtk.Image()
					img.set_from_pixbuf(item[2])
					menuitem.set_image(img)
				else:
					menuitem = gtk.MenuItem(item[0])
				if item[1] is not None:
					menuitem.connect("activate", item[1])
			self.append(menuitem)
			menuitem.show()
		return self

	def set_user(self, user):
		self.user = user
		
	def set_path(self, path):
		self.path = path
		
	def set_directory(self, directory):
		self.directory = directory
		
	def set_file(self, file):
		self.file = file
			
	def get_user(self):
		return self.user
		
	def OnSendMessage(self, widget):
		if DEBUG == True: print "OnSendMessage"
		self.frame.GetPrivateChat(self.user) 
	
	def OnShowIPaddress(self, widget):
		if DEBUG == True: print "OnShowIPaddress"
		self.frame.GetIPAddress(self.user)
	
	def OnDownloadFile(self, widget):
		if DEBUG == True: print "OnDownloadFile"
		if self.path != None:
			path = self.path
		else:
			
			if self.directory[-1] != "\\":
				path = self.directory+"\\"+self.file
			else:
				path = self.directory+self.file
		self.frame.Networking.DownloadFile(self.user, path)
		
		
	def OnDownloadDirectory(self, widget):
		if DEBUG == True: print "OnDownloadDirectory"
		if self.path != None:
			dire = ''	
			for path in self.path.split("\\")[:-1]:
				dire += path+"\\"
			
			self.frame.Networking.GetFolderContents(self.user, dire)
		else:
			self.frame.Networking.GetFolderContents(self.user, self.directory)

	
	def OnGetUserInfo(self, widget):
		if DEBUG == True: print "OnGetUserInfo", self.user
		self.frame.GetUserInfo(self.user)
		
	def OnBrowseUser(self, widget):
		self.frame.GetShares(self.user)
	
	def OnBuddyUser(self, widget):
		if widget.get_active():
			self.frame.Networking.mod_config("buddy", self.user)
		else:
			self.frame.Networking.mod_config("unbuddy", self.user)
	
	def OnBanUser(self, widget):
		if widget.get_active():
			self.frame.Networking.mod_config("ban", self.user)
		else:
			self.frame.Networking.mod_config("unban", self.user)
			
	def OnTrustUser(self, widget):
		if widget.get_active():
			self.frame.Networking.mod_config("trust", self.user)
		else:
			self.frame.Networking.mod_config("distrust", self.user)
			
	def OnIgnoreUser(self, widget):
		if widget.get_active():

			self.frame.Networking.mod_config("ignore", self.user)
		else:
			self.frame.Networking.mod_config("unignore", self.user)
			
	def OnLeaveRoom(self, widget):
		room = self.user
		self.frame.RoomLeave(room)
		
	def OnJoinRoom(self, widget):
		room = self.user
		self.frame.JoinARoom(room)

	
	def OnAbortDownTransfer(self, widget):
		self.frame.Networking.TransferAbort(0, self.user, self.path)
		
	def OnAbortUpTransfer(self, widget):
		self.frame.Networking.TransferAbort(1, self.user, self.path)
		
	def OnClearDownTransfer(self, widget):
		self.frame.Networking.TransferRemove(0, self.user, self.path)
		
	def OnClearUpTransfer(self, widget):
		self.frame.Networking.TransferRemove(1, self.user, self.path)
		
	def OnRetryTransfer(self, widget):	
		self.frame.Networking.DownloadFile(self.user, self.path)




class UserBrowse:
	def __init__(self, browses, user):
	
		self.frame = browses.frame
		self.browses = browses
		self.user = user 
		self.shares = {}
		self.selected_files = []
		self.files = {}
		self.directories = {}
		
		self.Main = gtk.VBox(False, 0)
		self.Main.show()
		self.Main.set_spacing(0)
		### Search Shares
		self.search_position = 0
		self.search_list = []
		self.query = None
		###
		hbox1 = gtk.HBox(False, 5)
		hbox1.show()
		hbox1.set_spacing(5)
		
		self.label1 = gtk.Label(("Search Shares For:"))
		self.label1.set_padding(5, 0)
		self.label1.show()
		hbox1.pack_start(self.label1, False, False, 5)
		
		self.entry = entry= gtk.Entry()
		entry.set_text("")
		#entry.set_activates_default(True)
		entry.set_editable(True)
		entry.connect_object("activate", self.SearchShares, user)
		entry.show()
		hbox1.pack_start(entry, True, True, 5)
		
		self.SearchButton = self.frame.CreateIconButton(gtk.STOCK_FIND, "stock", self.SearchShares, "Search")

		
		hbox1.pack_start(self.SearchButton, False, False, 5)
		
		self.RefreshButton = self.frame.CreateIconButton(gtk.STOCK_REFRESH, "stock", self.OnRefreshShares, "Refresh")

		
		hbox1.pack_start(self.RefreshButton, False, False, 5)
		
		self.Main.pack_start(hbox1, False, True, 0)
		
		hbox2 = gtk.HBox(False, 0)
		hbox2.show()
		hbox2.set_spacing(0)
		
		hpaned1 = gtk.HPaned()
		hpaned1.show()
		
		self.DirSW = DirSW = gtk.ScrolledWindow()
		self.DirSW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.DirSW.set_size_request(250, -1)
		self.DirSW.show()
		self.DirSW.set_shadow_type(gtk.SHADOW_IN)
		
		
		self.DirStore = gtk.TreeStore(  str, str )
		
		self.DirTreeView = DirTreeView = gtk.TreeView(self.DirStore)
		#self.DirTreeView.set_property("rules-hint", True)
		self.DirTreeView.set_enable_tree_lines(True)
		#DirTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		DirTreeView.set_headers_visible(True)
		cols = InitialiseColumns(self.DirTreeView,
			[_("Directories"), -1, "text"], #0
		)
		cols[0].set_sort_column_id(0)
		#self.DirTreeView.set_search_column(0)
		DirTreeView.show()
		
		#self.DirStore.set_sort_column_id(0, gtk.SORT_ASCENDING)
		
		self.dir_popup_menu = popup = PopupMenu(self.frame, "browse-dirs")
		popup.setup(
			("#" + _("_Download Directory"), self.OnDownloadDirectory, gtk.STOCK_GO_DOWN),
			("#" + _("_Download Recursively"), self.OnDownloadDirectoryRecursive, gtk.STOCK_GO_DOWN),
			("#" + _("_Upload Directory"), self.OnUploadDirectoryTo, gtk.STOCK_GO_UP),
			("#" + _("_Upload Recursively"), self.OnUploadDirectoryRecursiveTo, gtk.STOCK_GO_UP),
			("", None),
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Reload _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		self.dir_popup_menu.set_user(user)
		DirTreeView.connect("button_press_event", self.OnDirClicked)
		DirTreeView.get_selection().connect("changed", self.OnDirSelected)
		DirSW.add(DirTreeView)

		
		hpaned1.pack1(DirSW, False, False)
		self.FilesStore = self.FileStore = gtk.ListStore(  str, str, str, int, str, int )
		
		self.FilesTreeView = gtk.TreeView(self.FileStore)
		self.FilesTreeView.set_property("rules-hint", True)
		self.FilesTreeView.set_reorderable(True)
		self.FilesTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		self.FilesTreeView.set_headers_visible(True)
		
		cols = InitialiseColumns(self.FilesTreeView,
		[_("Filename"), 250, "text"], #0
		[_("Size"), 100, "text"], #1
		[_("Length"), 70, "text"], #2
		[_("Bitrate"), 70, "text"], #3
		)
		#for ix in range(len(cols)):
		cols[0].set_sort_column_id(0)
		cols[1].set_sort_column_id(5)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		
		self.files_popup_menu = popup = PopupMenu(self.frame, "browse-files")
		popup.setup(
			("#" + _("Download _File(s)"), self.OnDownloadFiles, gtk.STOCK_GO_DOWN),
			("#" + _("_Download Directory"), popup.OnDownloadDirectory, gtk.STOCK_GO_DOWN),
			("#" + _("Upload _File(s)"), self.OnUploadFiles, gtk.STOCK_GO_UP),
			("", None),
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("_IP Address"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Reload _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		self.files_popup_menu.set_user(user)
		self.FilesTreeView.connect("button_press_event", self.OnFileClicked)
		self.FilesTreeView.show()
		
		self.FilesSW = gtk.ScrolledWindow()
		self.FilesSW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.FilesSW.set_shadow_type(gtk.SHADOW_IN)
		self.FilesSW.add(self.FilesTreeView)
		self.FilesSW.show()
		directory = self.BrowseGetDirs(user)
		self.BrowseChangeDir(user, directory)
		
		hpaned1.pack2(self.FilesSW, True, True)
		
		hbox2.pack_start(hpaned1, True, True, 0)
		
		self.Main.pack_start(hbox2, True, True, 0)
			
		
	def OnDirSelected(self, selection):
		model, iter = selection.get_selected()
		if iter is None:
			self.selected_folder = None
			self.BrowseChangeDir(self.user, None)
			return
		path = model.get_path(iter)
		directory = self.DirStore.get_value(self.DirStore.get_iter(path), 1)
		self.selected_folder = directory
		self.BrowseChangeDir(self.user, directory)
		
	def OnDownloadDirectory(self, widget):
		self.DownloadDirectory(self.selected_folder)
	
	def DownloadDirectory(self, dir, prefix = "", recurse = 0):
		if dir == None:
			return
		ldir = prefix + dir[:-1].split("\\")[-1]
		for file in self.shares[dir]:
			self.frame.Networking.DownloadFileTo(self.user, "\\".join([dir, file]), ldir)

		if not recurse:
			return
		for directory in self.shares.keys():
			if dir in directory and dir != directory:
	
				self.DownloadDirectory(directory, os.path.join(ldir, ""), recurse)
				
	def DownloadDirectoryRecursive(self, dir, prefix = ""):
		# Find all files and add them to list
		if dir == None:
			return
		localdir = prefix + dir[:-1].split("\\")[-1]
		files = []
		
		if dir in self.shares.keys():
			for file in self.shares[dir]:
				files.append(["\\".join([dir, file]), localdir])
		
		for directory in self.shares.keys():
			if dir in directory and dir != directory:
				files += self.DownloadDirectoryRecursive(directory, os.path.join(localdir, ""))
	
		return files

	def OnDownloadDirectoryRecursive(self, widget):

		prefix = ""
		dir = self.selected_folder 
		if dir == None:
			return
		localdir = prefix + dir[:-1].split("\\")[-1]

		files = []
		files += self.DownloadDirectoryRecursive(dir, os.path.join(localdir, ""))
		
		# Check the number of files to be downloaded, just to make sure we aren't accidently downloading hundreds or thousands
		numfiles = len(files)
		go_ahead=0
		if len(files) > 100:
			go_ahead = Option_Box(self.frame, title=_('Murmur: Download %i files?' %numfiles), message=_("Are you sure you wish to download %i files from %s's directory %s?" %( numfiles, self.user, dir ) ), option1=_("Ok"), option3=_("Cancel"), option2=None, status="warning" )
			
		else:
			go_ahead = 1
			
		if go_ahead == 1:
			# Good to go, we download these
			for item in files:
				file, localpath = item
				#self.frame.np.transfers.getFile(self.user, file, localpath)
				self.frame.Networking.DownloadFileTo(self.user, file, localpath)

			
	def OnUploadDirectoryRecursiveTo(self, widget):
		self.OnUploadDirectoryTo(widget, recurse=1)
	
	def UploadDirectoryTo(self, user, dir, recurse = 0):
		if dir == None:
			return

		ldir = dir[:-1].split("\\")[-1]
		
		if user is None or user == "":
			return
		else:
			if dir in self.shares.keys():

				for file in self.shares[dir]:
					self.frame.Networking.UploadFile(user, "%s\\%s" %(dir, file) )
		
		if not recurse:
			return

		for directory in self.shares.keys():
			if dir in directory and dir != directory:
				self.UploadDirectoryTo(user, directory, recurse)
				
	def OnUploadDirectoryTo(self, widget, recurse = 0):
		dir = self.selected_folder
		if dir == None:
			return
	
		users = []
		for user in self.frame.Networking.config["buddies"]:
			users.append(user)
		users.sort()
		user = input_box(self.frame, title=_("Nicotine: Upload Directory's Contents"),
		message=_('Enter the User you wish to upload to:'),
		default_text='', droplist=users)
		self.UploadDirectoryTo(user, dir, recurse)
		
	def OnDownloadFiles(self, widget, prefix = ""):
		dir = self.selected_folder
		for fn in self.selected_files:
			self.frame.Networking.DownloadFileTo(self.user, "\\".join([dir, fn]), prefix)
			
	def OnDownloadFilesTo(self, widget):
		ldir = ChooseDir(self.frame.MainWindow, self.frame.Config["transfers"]["downloaddir"])
		if ldir is None:
			return

		for directory in ldir: # iterate over selected files
			try:
 				self.OnDownloadFiles(widget, directory)
				
			except IOError: # failed to open
				self.message('failed to open %r for reading', directory) # notify user
	
	def OnUploadFiles(self, widget, prefix = ""):
		dir = self.selected_folder
		users = []
		for user in self.frame.Networking.config["buddies"]:
			users.append(user)
		users.sort()
		username = input_box(self.frame, title=_('Murmur: Upload File(s)'),
		message=_('Enter the User you wish to upload to:'),
		default_text='', droplist=users)
		if username is None or username == "":
			pass
		else:
			for path in self.selected_files:
				self.frame.Networking.UploadFile(username, "%s\\%s" %(self.directory, path) )
				
	def OnDirClicked(self, widget, event):
		if event.button != 3:
			self.MouseAction(widget, event)
			return
		self.OnDirPopupMenu(widget, event)
			
	def OnDirPopupMenu(self, widget, event):
		user = self.user
		menu = self.dir_popup_menu
		items = menu.get_children()
		
		d = self.DirTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		directory = self.DirStore.get_value(self.DirStore.get_iter(path), 1)
		menu.set_directory(directory)
		num = 9
		
		
		if self.frame.Networking.config != {}:
			items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
			items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
			items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
			items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))
		menu.popup(None, None, None, event.button, event.time)
			
	def SelectedFilesCallback(self, model, path, iter):
		self.selected_files.append(self.FileStore.get_value(iter, 0))
		
	def OnFileClicked(self, widget, event):
		if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
			# Double-Left-Click
			self.selected_files = []
			self.FilesTreeView.get_selection().selected_foreach(self.SelectedFilesCallback)
			self.OnDownloadFiles(widget)
			self.FilesTreeView.get_selection().unselect_all()
			return True
		elif event.button == 3:
			# Right-click
			self.selected_files = []
			self.FilesTreeView.get_selection().selected_foreach(self.SelectedFilesCallback)
			return self.OnFilePopupMenu(widget, event)
		# Left-click / etc
		return False
		
	def OnFilePopupMenu(self, widget, event):
		user = self.files_popup_menu.user
		items = self.files_popup_menu.get_children()
		
		if DEBUG == True:  print "-- Popup -- :"
		
		d = self.FilesTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		
		file = self.FileStore.get_value(self.FileStore.get_iter(path), 0)
		directory = self.FileStore.get_value(self.FileStore.get_iter(path), 4)
		self.files_popup_menu.set_file(file)
		self.files_popup_menu.set_directory(directory)
		num = 8

		if self.frame.Networking.config != {}:
			items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
			items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
			items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
			items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))

		
		self.FilesTreeView.emit_stop_by_name("button_press_event")
		self.files_popup_menu.popup(None, None, None, event.button, event.time)
		return True
		
	def MouseAction(self, widget, event):
		if DEBUG == True:  print "-- Click -- :"

		d = self.DirTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		directory = self.DirStore.get_value(self.DirStore.get_iter(path), 1)
		if DEBUG == True:  print "-- dir :", directory
		self.BrowseChangeDir(self.user, directory)
		
	def SetSensitive(self, bool):
		self.DirTreeView.set_sensitive(bool)
		self.FilesTreeView.set_sensitive(bool)
		self.SearchButton.set_sensitive(bool)
		self.RefreshButton.set_sensitive(bool)
		self.entry.set_sensitive(bool)
		self.label1.set_sensitive(bool)
		
	def ShowShares(self, user, shares):
		try:
			
			if user != self.user:
				return
			self.DirStore.clear()
			self.shares = shares
			directory = self.BrowseGetDirs(user)
			self.BrowseChangeDir(user, directory)
			self.DirTreeView.expand_all()
			self.SetSensitive(True)
			
		except Exception,e:
			if DEBUG == True: print "get_shares", Exception,e
			
	def OnClose(self, user):
		self.browses.RemoveTab(self)
		
	def OnRefreshShares(self, widget):
		self.SetSensitive(False)
		self.frame.GetShares(self.user)
		
	def SearchShares(self, widget):
		query = self.entry.get_text()
		if self.query == query:
			self.search_position += 1
		else: 
			self.search_position = 0
		self.query = query
		if self.query == "":
			return
		if DEBUG == True: print "Query:", query
		dir = self.directory
		self.search_list = []
		
		searchfilter = re.compile('.*' +str(query) + '.*', re.DOTALL | re.I)

		for directory, files in self.shares.items():
			if directory == dir:
				continue
			if re.match(searchfilter, directory):
				if directory not in self.search_list:
					self.search_list.append(directory)
			for file in files.keys():
				if re.match(searchfilter, file):
					if directory not in self.search_list:
						self.search_list.append(directory)
		if self.search_list != []:
			if self.search_position not in range(len(self.search_list)):
				self.search_position = 0
			self.search_list.sort()
			directory = self.search_list[self.search_position]
			#self.BrowseChangeDir(user, directory)
			## Set directory position to be the searched directory
			self.DirTreeView.set_cursor(self.DirStore.get_path(self.directories[directory]))
			
			# Get matching files in the current directory
			resultfiles = []
			for file in self.shares[directory]:
				if re.match(searchfilter, file):
					resultfiles.append(file)
					
			sel = self.FilesTreeView.get_selection()
			sel.unselect_all()
			l = 1
			resultfiles.sort()
			for fn in resultfiles:
				path = self.FilesStore.get_path(self.files[fn])
				# Select each matching file in directory
				sel.select_path(path)
				if l:
					# Position cursor at first match
					#self.FilesTreeView.set_cursor(path)
					self.FilesTreeView.scroll_to_cell(path, None, True, 0.5, 0.5)
					l = 0


		else:
			self.search_position = 0

		
	def BrowseGetDirs( self, user):
		try:
			z = []
			for dirs in self.shares.keys():
				z.append(dirs)
			z.sort()
			zz = []
			directory = ""
			self.directories = {}
			if z != []:
				for item in z:
					s = item.split("\\")
					path = ''

					parent = s[0]
					if parent == '':
						parent += "\\"
						if parent not in self.directories.keys():
							self.directories[parent] =  self.DirStore.append(None, [parent, parent])
					parent = s[0]
					for seq in s[1:]:
						if parent == "":
							parent += "\\"
							path = parent+seq
						else:
							path = parent+"\\"+seq
						

						if parent not in self.directories.keys():
							self.directories[parent] =  self.DirStore.append(None, [parent, parent])
						

						if path not in zz:
							zz.append(path)
							self.directories[path] = self.DirStore.append(self.directories[parent], [path.split("\\")[-1], path ] )
						parent = path

				directory = zz[0]
			return directory
		except Exception,e:
			if DEBUG == True: print "BrowseGetDirs", Exception,e
			
	def BrowseChangeDir(self, user, directory):
		self.directory = directory
		self.FileStore.clear()
		self.files = {}
		if not self.shares.has_key(directory):
			return
		path = self.DirStore.get_path( self.directories[directory] )
		self.DirTreeView.expand_to_path(path)
		#file, stats[ size, ftype, [bitrate, length ] ]
		if directory in self.shares:
			for files,stats in self.shares[directory].items():
				#print files, stats
				size, ftype, attr  = stats
				#[bitrate, length, something ]
				if ftype == "" or attr == []:
					length = 0
					bitrate = 0
				else:
					bitrate = attr[0]
					length = self.frame.Length2Time(attr[1])

				iter = self.FileStore.append([files, self.frame.Humanize(size), length, bitrate, directory, int(size)])
				self.files[files] = iter
			
		# Finish
		self.FileStore.set_sort_column_id(0, gtk.SORT_ASCENDING)
			
class UserBrowses(IconNotebook):
	def __init__(self, frame):
		IconNotebook.__init__(self, frame.images)
		self.set_scrollable(True)
		self.show()
		self.users = {}
		self.frame = frame
		self.set_border_width(4)
		self.set_tab_pos(gtk.POS_TOP)
		self.connect("switch-page", self.OnSwitchPage)
		
	def GotUserBrowse(self, user, shares):
		if self.users.has_key(user):
			self.users[user].ShowShares(user, shares)
		else:
			self.users[user] = UserBrowse(self, user)
		
			self.append_page(self.users[user].Main, user[:15], self.users[user].OnClose)

			self.users[user].ShowShares(user, shares)
		self.request_changed(self.users[user].Main)
		self.frame.RequestIcon(self.frame.UserBrowseLabel)	
	def OnSwitchPage(self, notebook, page, page_num, force = 0):
		
		if self.frame.notebook_outside.get_current_page() != 4 and not force:
			return
		page = notebook.get_nth_page(page_num)	
		#print page
		
	def RemoveTab(self, tab):
		self.remove_page(self.page_num(tab.Main))
		del self.users[tab.user]
		tab.Main.destroy()
		del tab
		gc.collect()
		
class UserInfo:
	def __init__(self, infos, user):
		self.frame = infos.frame
		self.userinfos = infos
		self.user = user

		userinfoVbox = gtk.VBox(False, 0)
		userinfoVbox.show()
		userinfoVbox.set_spacing(0)

		scrolledwindow1 = gtk.ScrolledWindow()
		scrolledwindow1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		scrolledwindow1.show()
		scrolledwindow1.set_shadow_type(gtk.SHADOW_OUT)
	
		self.UserInfoText = UserInfoText = gtk.TextView()
		UserInfoText.set_wrap_mode(gtk.WRAP_WORD)
		UserInfoText.set_cursor_visible(True)
		UserInfoText.set_editable(False)
		self.textbuffer = textbuffer = UserInfoText.get_buffer()
		#textbuffer.set_text(info)
		UserInfoText.show()
		scrolledwindow1.add(UserInfoText)
	
		userinfoVbox.pack_start(scrolledwindow1, True, True, 5)
	
		vboxstats = gtk.VBox(False, 0)
		vboxstats.show()
		vboxstats.set_spacing(5)
		vboxstats.set_border_width(4)
		#  
		hbox2 = gtk.HBox(False, 0)
		hbox2.show()
		hbox2.set_spacing(0)
	
		label4 = gtk.Label(("Slots:"))
		label4.set_padding(0, 0)
		label4.show()
		hbox2.pack_start(label4, False, False, 0)
	
		self.SlotsNum = SlotsNum = gtk.Label() # str(slotsfree)
		SlotsNum.set_padding(0, 0)
		SlotsNum.show()
		hbox2.pack_start(SlotsNum, False, False, 5)
		label6 = gtk.Label(("Uploads allowed:"))
		label6.set_padding(0, 0)
		label6.show()
		
		hbox2.pack_start(label6, False, False, 5)
	
		self.UploadsAllowed = UploadsAllowed = gtk.Label() #str(uploads) 
		UploadsAllowed.set_padding(0, 0)
		UploadsAllowed.show()
		hbox2.pack_start(UploadsAllowed, False, False, 5)
		
	
		vboxstats.pack_start(hbox2, False, False, 0)
	
		hbox5 = gtk.HBox(False, 0)
		hbox5.show()
		hbox5.set_spacing(0)
	
		label7 = gtk.Label(("Queue:"))
		label7.set_padding(0, 0)
		label7.show()
		hbox5.pack_start(label7, False, False, 0)
	
		self.QueueNum = QueueNum = gtk.Label() # str(queue)
		QueueNum.set_padding(0, 0)
		QueueNum.show()
		hbox5.pack_start(QueueNum, False, False, 5)
	
		label8 = gtk.Label(("Files:"))
		label8.set_padding(0, 0)
		label8.show()
		hbox5.pack_start(label8, False, False, 0)

		self.FilesNum = FilesNum = gtk.Label() # str(files)
		FilesNum.set_padding(0, 0)
		FilesNum.show()
		hbox5.pack_start(FilesNum, False, False, 5)
		
		label82 = gtk.Label(("Speed:"))
		label82.set_padding(0, 0)
		label82.show()
		hbox5.pack_start(label82, False, False, 0)
		
		self.SpeedNum = SpeedNum = gtk.Label() # str(speed)
		SpeedNum.set_padding(0, 0)
		SpeedNum.show()
		hbox5.pack_start(SpeedNum, False, False, 5)
	
		vboxstats.pack_start(hbox5, False, False, 0)
	
		hboxbuttons = gtk.HBox(False, 0)
		hboxbuttons.show()
		hboxbuttons.set_spacing(5)

		close_button = gtk.Button("Close", stock="gtk-close")
		close_button.connect_object("clicked", self.OnClose, user)
		close_button.show()
		
		hboxbuttons.pack_start(close_button, False, False, 0)
		
		refresh_button = gtk.Button("Refresh", stock="gtk-refresh")
		refresh_button.connect_object("clicked", self.refresh_userinfo, user)
		refresh_button.show()	
		hboxbuttons.pack_start(refresh_button, False, False, 0)

		vboxstats.pack_start(hboxbuttons, False, False, 5)
		userinfoVbox.pack_start(vboxstats, False, False, 0)
		
		
		self.ScrollPicture = gtk.ScrolledWindow()
		self.ScrollPicture.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.ScrollPicture.set_shadow_type(gtk.SHADOW_OUT)
		self.UserImage = gtk.Image()
		self.UserImage.show()
		
		self.ScrollPicture.add_with_viewport(self.UserImage)
		self.ScrollPicture.show()

		self.Main = gtk.HPaned()
		self.Main.set_border_width(4)
		
		self.Main.pack1(userinfoVbox, False, True)
		self.Main.pack2(self.ScrollPicture, True, True)
		self.Main.show()

		
	def OnClose(self, user):
		self.userinfos.remove_page(self.Main)
		del self.userinfos.users[self.user]
		self.Main.destroy()

	def refresh_userinfo(self, user):
		self.frame.Networking.UserInfo(user)

	def ShowInfo(self, user, info, picture, uploads, queue, slotsfree):
		if DEBUG == True:
			print "%s info received"%  user
		textbuffer  = self.textbuffer
		UserInfoText = self.UserInfoText
		textbuffer = UserInfoText.get_buffer()
		textbuffer.set_text(info)

		self.SlotsNum.set_label( str(slotsfree) )
		self.QueueNum.set_label( str(queue) )
		self.UploadsAllowed.set_label( str(uploads) )
		
		if user in self.frame.user_stats:
			self.files = abs( self.frame.user_stats[user][3] )
			self.speed =  abs(self.frame.user_stats[user][1])
		else:
			self.speed = self.files = 0
			
		self.SpeedNum.set_label(str(self.speed))
		self.FilesNum.set_label(str(self.files))
		
		if picture != None and picture != "":
			s = gtk.gdk.PixbufLoader()
			s.write(picture)
			s.close()
			if DEBUG == True:
				print "drawing image for", user
			self.UserImage.set_from_pixbuf(s.get_pixbuf())
			self.UserImage.show()
			del s, picture
			gc.collect()
		else:
			self.UserImage.set_from_pixbuf(None)
		

class UserInfos(IconNotebook):
	def __init__(self, frame):
		IconNotebook.__init__(self, frame.images)
		self.set_scrollable(True)
		self.show()
		self.users = {}
		self.frame = frame
		self.set_border_width(4)
		self.set_tab_pos(gtk.POS_TOP)
		self.connect("switch-page", self.OnSwitchPage)
		
	def GotUserInfo(self, user, info, picture, uploads, queue, slotsfree):
		#self.frame.UserInfoLabel.set_image(self.images["online"])
		self.frame.RequestIcon(self.frame.UserInfoLabel)
		if self.users.has_key(user):
			self.users[user].ShowInfo(user, info, picture, uploads, queue, slotsfree)
		else:
			self.users[user] = UserInfo(self, user)

			self.append_page(self.users[user].Main, user[:15], self.users[user].OnClose)
			

			self.users[user].ShowInfo(user, info, picture, uploads, queue, slotsfree)
		self.request_changed(self.users[user].Main)
	def OnSwitchPage(self, notebook, page, page_num, force = 0):
		
		if self.frame.notebook_outside.get_current_page() != 4 and not force:
			return
		page = notebook.get_nth_page(page_num)	
		
	def RemoveTab(self, tab):
		self.remove_page(self.page_num(tab.Main))
		del self.users[tab.user]
		
class PrivateChat:
	def __init__(self, chats, user):
		self.chats  = chats
		self.frame = chats.frame
		self.user = user
		self.Status = 0
		self.Main = gtk.VBox(False, 0)
		self.Main.show()
		self.Main.set_spacing(0)
	
		self.scrolledwindow16 = gtk.ScrolledWindow()
		self.scrolledwindow16.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.scrolledwindow16.show()
		self.scrolledwindow16.set_shadow_type(gtk.SHADOW_IN)
	
		self.ChatScroll = gtk.TextView()
		self.ChatScroll.set_wrap_mode(gtk.WRAP_WORD)
		self.ChatScroll.set_cursor_visible(False)
		self.ChatScroll.set_editable(False)
		self.ChatScroll.show()
		self.scrolledwindow16.add(self.ChatScroll)
	
		self.Main.pack_start(self.scrolledwindow16, True, True, 0)
	
		self.hbox5 = gtk.HBox(False, 5)
		self.hbox5.show()
		#self.hbox5.set_spacing(0)
	
		self.ChatLine = gtk.Entry()
		self.ChatLine.set_text("")
		self.ChatLine.set_editable(True)
		self.ChatLine.show()
		self.ChatLine.set_visibility(True)
		self.ChatLine.connect("activate", self.OnEnter)
		self.ChatLine.connect("key_press_event", self.OnKeyPress)
		
		self.hbox5.pack_start(self.ChatLine, True, True, 5)
		self.hbox5.set_focus_child(self.ChatLine)
		
		self.Encoding_List = gtk.ListStore(gobject.TYPE_STRING)
		self.Encoding = gtk.ComboBox()
		self.Encoding.show()
		#self.Encoding.connect("changed", self.OnEncodingChanged)
	
		self.Encoding.set_model(self.Encoding_List)
		cell = gtk.CellRendererText()
		self.Encoding.pack_start(cell, True)
		self.Encoding.add_attribute(cell, 'text', 0)
		self.hbox5.pack_start(self.Encoding, False, False, 0)
	
		self.Log = gtk.CheckButton()
		self.Log.set_active(False)
		self.Log.set_label(_("Log"))
		self.Log.show()
		#self.Log.connect("toggled", self.OnLogToggled)
		self.hbox5.pack_start(self.Log, False, False, 5)
		self.button1 = self.frame.CreateIconButton(gtk.STOCK_CLOSE, "stock", self.OnClose, _("Close"))

	
		self.hbox5.pack_start(self.button1, False, False, 5)
	
		self.Main.pack_start(self.hbox5, False, True, 0)
		self.Main.set_focus_child(self.hbox5)
	
	
		
		self.popup_menu = popup = PopupMenu(self.frame, "something")
		popup.setup(
			("#" + _("Close"), self.OnClose, gtk.STOCK_CLOSE),
			("", None),
			("#" + _("Show IP address"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Get user info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("Browse files"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			#(_("Give privileges"), popup.OnGivePrivileges),
			("$" + _("Add user to list"), popup.OnBuddyUser),
			("$" + _("Ban this user"), popup.OnBanUser),
			("$" + _("Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
			#(_("Client Version"), popup.OnVersion ),
		)
		popup.set_user(user)
		self.ChatScroll.connect("button_press_event", self.OnPopupMenuPrivate)
		self.ChatLine.grab_focus()
		self.UpdateColours()
		
	def UpdateColours(self):
		def makecolour(buffer, colour):
			if self.frame.Config["colors"].has_key(colour):
				colour = self.frame.Config["colors"][colour]
			else:
				colour = "#AAFF00"
			font = self.frame.Config["colors"]["chatfont"]
			
			if colour:
				return buffer.create_tag(foreground = colour, font=font)
			else:
				return buffer.create_tag( font=font)

				
		buffer = self.ChatScroll.get_buffer()
		self.tag_remote = makecolour(buffer, "chatremote")
		self.tag_local = makecolour(buffer, "chatlocal")
		self.tag_me = makecolour(buffer, "chatme")
		self.tag_hilite = makecolour(buffer, "chathilite")
		
		if self.frame.user_stats.has_key(self.user):
			status = self.frame.user_stats[self.user][0]
			if status == 1:
				color = "useraway"
			elif status == 2:
				color = "useronline"
			else:
				color = "useroffline"
		else:
			color = "useroffline"
		self.tag_username = makecolour(buffer, color)

		
	def changecolour(self, tag, colour):
		if self.frame.Config["colors"].has_key(colour):
			colour = self.frame.Config["colors"][colour]
		else:
			colour = ""
		font = self.frame.Config["colors"]["chatfont"]
		
		if colour:
			tag.set_property("foreground", colour)
			tag.set_property("font", font)
		else:
			tag.set_property("font", font)
			
	def ChangeColours(self):
		
				
		self.changecolour(self.tag_remote, "chatremote")
		self.changecolour(self.tag_local, "chatlocal")
		self.changecolour(self.tag_me, "chatme")
		self.changecolour(self.tag_hilite, "chathilite")
		self.changecolour(self.tag_username, color)
		self.setStatus()
		
	def setStatus(self):
		
		if self.frame.user_stats.has_key(self.user):

			if self.Status == self.frame.user_stats[self.user][0]:
				return
			self.Status = self.frame.user_stats[self.user][0]
			if self.Status == 1:
				color = "useraway"
			elif self.Status == 2:
				color = "useronline"
			else:
				color = "useroffline"
		else:
			color = "useroffline"
			self.Status = 0

		self.changecolour(self.tag_username, color)
		
	def OnClose(self, widget):
		#if self.logfile is not None:
			#self.logfile.close()
			#self.logfile = None
		self.chats.remove_page(self.Main)
		del self.chats.users[self.user]
		self.Main.destroy()

	def ShowMessage(self, direction, text):
		if self.user == self.frame.username:
			tag = self.tag_local
		elif text.upper().find(self.frame.username.upper()) > -1:
			tag = self.tag_hilite
		else:
			tag = self.tag_remote
		
		if direction == 0:
			username = self.user
		else:
			username = self.frame.username
				
		if text[:4] == "/me ":
			line = "* %s %s" % (username, text[4:])
			tag = self.tag_me
		else:
			line = "[%s] %s" % (username, text)
		self.frame.RequestIcon(self.frame.PrivateChatLabel)
		AppendLine(self.ChatScroll, line, tag, "%c", username=self.user, usertag=self.tag_username)
		#if self.z:
			#self.z = 0
			#self.tag_username.set_property("foreground", "#00FF00")
		#else:
			#self.z = 1
			#self.tag_username.set_property("foreground", "#FF0000")
		#if self.Log.get_active():
			#self.logfile = WriteLog(self.logfile, self.frame.np.config.sections["logging"]["logsdir"], self.user, line)
		
		#autoreply = self.frame.np.config.sections["server"]["autoreply"]
		#if self.frame.away and not self.autoreplied and autoreply:
			#self.SendMessage("[Auto-Message] %s" % autoreply)
			#self.autoreplied = 1

	def SendMessage(self, text):

		if text[:4] == "/me ":
			line = "* %s %s" % (self.frame.username, text[4:])
			tag = self.tag_me
		else:
			
			if text == "\x01VERSION\x01":
				line = "CTCP VERSION"
			else:
				line = "[%s] %s" % (self.frame.username, text)
			tag = self.tag_local
			
		AppendLine(self.ChatScroll, line, tag, "%c", username=self.user, usertag= self.tag_username)
		#if self.Log.get_active():
			#self.logfile = WriteLog(self.logfile, self.frame.np.config.sections["logging"]["logsdir"], self.user, line)
		

		
	COMMANDS = ["/alias ", "/unalias ", "/whois ", "/browse ", "/ip ", "/pm ", "/msg ", "/search ", "/usearch ", "/rsearch ", "/bsearch ", "/join ", "/leave", "/add ", "/buddy ", "/unbuddy ", "/ban ", "/ignore ", "/unban ", "/unignore ", "/clear", "/part ", "/quit", "/rescan", "/tick", "/nsa", "/info", "/ctcpversion", "/rem ", "/cl", "/t", "/a", "/q", "/l", "/p", "/bs", "/rs", "/us", "/s", "/m", "/w", "/al", "/un", "/w", "/updatenormal", "/updatebuddy", "/rescannormal", "/rescanbuddy", "/addnormaldir", "/addbuddydir", "/removenormaldir", "/removebuddydir", "/listshares", "/listnormal", "/listbuddy" ]
				
	def destroy(self):
		#if self.frame.translux:
			#self.frame.translux.unsubscribe(self.tlux_chat)
		self.Main.destroy()

	def OnPopupMenuPrivate(self, widget, event):
		if event.button != 3:
			return
		items = self.popup_menu.get_children()
		#items[6].set_active(self.user in [i[0] for i in self.frame.np.config.sections["server"]["userlist"]])
		#items[7].set_active(self.user in self.frame.np.config.sections["server"]["banlist"])
		#items[8].set_active(self.user in self.frame.np.config.sections["server"]["ignorelist"])
		user = self.user
		num = 5
		items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.ChatScroll.emit_stop_by_name("button_press_event")
		return True
		
	def OnEnter(self, widget):
		text = widget.get_text()
		
		result = None
		#result = expand_alias(self.frame.np.config.aliases, text)
		if result is not None:
			text = result
		if not text:
			widget.set_text("")
			return
			
		s = text.split(" ", 1)
		cmd = s[0]
		if len(s) == 2 and s[1]:
			realargs = args = s[1]
		else:
			args = self.user
			realargs = ""

		#if cmd in ("/alias", "/al"):
			#AppendLine(self.ChatScroll, self.frame.np.config.AddAlias(realargs), None, "")
		#elif cmd in ("/unalias", "/un"):
			#AppendLine(self.ChatScroll, self.frame.np.config.Unalias(realargs), None, "")
		if cmd in ["/w", "/whois", "/info"]:
			if args:
				self.frame.GetUserInfo(args)
				self.frame.OnUserInfo(None)
		elif cmd in ["/b", "/browse"]:
			if args:
				self.frame.GetShares(args)
				self.frame.OnUserShares(None)
		elif cmd == "/ip":
			if args:
				if args not in self.frame.ip_requested:
					self.frame.ip_requested.append(args)
					self.frame.Networking.PeerAddress(args)
			else:
				if self.user not in self.frame.ip_requested:
					self.frame.ip_requested.append(self.user)
					self.frame.Networking.PeerAddress(self.user)
		elif cmd == "/nsa":
			if args:
				self.frame.GetUserInfo(args)
				self.frame.GetShares(args)
				self.frame.OnUserInfo(None)
				
		elif cmd == "/reload":
			self.Networking.ReloadShares()
			
		elif cmd == "/pm":
			if realargs:
				self.frame.PrivateChats.SendMessage(realargs, None, 1)
		elif cmd in ["/m", "/msg"]:
			if realargs:
				s = realargs.split(" ", 1)
				user = s[0]
				if len(s) == 2:
					msg = s[1]
				else:
					msg = None
				self.frame.PrivateChats.SendMessage(user, msg)
		elif cmd in ["/s", "/search"]:
			if realargs:
				self.frame.Networking.Search(0, realargs)
				self.frame.OnSearch(None)
		elif cmd in ["/us", "/usearch"]:
			s = args.split(" ", 1)
			if len(s) == 2:
				self.frame.Networking.Search(3, s[1], s[0])
				self.frame.OnSearch(None)
			else:
				return
		elif cmd in ["/rs", "/rsearch"]:
			if realargs:
				self.frame.Networking.Search(1, realargs)
				self.frame.OnSearch(None)
		elif cmd in ["/bs", "/bsearch"]:
			if realargs:
				self.frame.Networking.Search(2, realargs)
				self.frame.OnSearch(None)
		elif cmd in ["/ad", "/add", "/buddy"]:
			if args:
				self.frame.Networking.mod_config("buddy", args)
		elif cmd in ["/rem", "/unbuddy"]:
			if args:
				self.frame.Networking.mod_config("unbuddy", args)
		elif cmd == "/ban":
			if args:
				self.frameNetworking.mod_config("ban", args)
		elif cmd == "/unban":
			if args:
				self.frame.Networking.mod_config("unban", args)
		elif cmd == "/ignore":
			if args:
				self.frame.Networking.mod_config("ignore", args)
		elif cmd == "/unignore":
			if args:
				self.frame.Networking.mod_config("unignore", args)
		elif cmd == "/trust":
			if args:
				self.frame.Networking.mod_config("trust", args)
		elif cmd == "/distrust":
			if args:
				self.frame.Networking.mod_config("distrust", args)
		elif cmd == "/ctcpversion":
			if args:
				self.frame.Networking.PrivateMessage(0, args, "\x01VERSION\x01")
			else:
				self.frame.Networking.PrivateMessage(0, self.user, "\x01VERSION\x01")
		elif cmd in ["/clear", "/cl"]:
			self.chatview.get_buffer().set_text("")
		elif cmd in ["/a", "/away"]:
			self.frame.OnAway(None)
		elif cmd in ["/q", "/quit"]:
			self.frame.OnExit(None)
		elif cmd in ["/c", "/close", "/l", "/leave", "/part", "/p"]:
			self.OnClose(None)
			
		elif cmd == "/updatenormal":
			self.frame.Muscan.UpdateNormal()
		elif cmd == "/updatebuddy":
			self.frame.Muscan.UpdateBuddy()
		elif cmd == "/rescan":
			self.frame.Muscan.RescanNormal()
			self.frame.Muscan.RescanBuddy()
		elif cmd == "/rescannormal":
			self.frame.Muscan.RescanNormal()
		elif cmd == "/rescanbuddy":
			self.frame.Muscan.RescanBuddy()
		
		elif cmd == "/addnormaldir":
			if args:
				self.frame.Muscan.AddNormalDirectory(args)
			else:
				return
		elif cmd == "/removenormaldir":
			if args:
				self.frame.Muscan.RemoveNormalDirectory(args)
			else:
				return
		elif cmd == "/addbuddydir":
			if args:
				self.frame.Muscan.AddBuddyDirectory(args)
			else:
				return
		elif cmd == "/removebuddydir":
			if args:
				self.frame.Muscan.RemoveBuddyDirectory(args)
			else:
				return
		elif cmd == "/listshares":
			self.frame.Muscan.ListNormal()
			self.frame.Muscan.ListBuddy()
		elif cmd == "/listnormal":
			self.frame.Muscan.ListNormal()
		elif cmd == "/listbuddy":
			self.frame.Muscan.ListBuddy()

			
		elif cmd and cmd[:1] == "/" and cmd != "/me" and cmd[:2] != "//":
			self.frame.AppendToLogWindow(_("Command %s is not recognized") % text)
			return
		else:
			if text[:2] == "//":
				text = text[1:]
			self.SendMessage(text)
			self.frame.Networking.PrivateMessage(0, self.user, text)
		widget.set_text("")
		
	def OnKeyPress(self, widget, event):
		
		if event.keyval == gtk.gdk.keyval_from_name("Prior"):
			scrolled = self.ChatScroll.get_parent()
			adj = scrolled.get_vadjustment()
			adj.set_value(adj.value - adj.page_increment)
		elif event.keyval == gtk.gdk.keyval_from_name("Next"):
			scrolled = self.ChatScroll.get_parent()
			adj = scrolled.get_vadjustment()
			max = adj.upper - adj.page_size
			new = adj.value + adj.page_increment
			if new > max:
				new = max
			adj.set_value(new)
		if event.keyval != gtk.gdk.keyval_from_name("Tab"):
			return False
		ix = widget.get_position()
		text = widget.get_text()[:ix].split(" ")[-1]
		list = [self.user] + [i for i in self.frame.Networking.config["buddies"]] + ["museek"]
		if ix == len(text) and text[:1] == "/":
			list +=  self.COMMANDS 
			#self.frame.np.config.aliases.keys()] +

		completion, single = self.frame.GetCompletion(text, list)
		if completion:
			widget.insert_text(completion, ix)
			widget.set_position(ix + len(completion))
		widget.emit_stop_by_name("key_press_event")
		return True
		
class PrivateChats(IconNotebook):
	def __init__(self, frame):
		IconNotebook.__init__(self, frame.images)
		self.set_scrollable(True)
		self.show()
		self.users = {}
		self.frame = frame
		self.set_border_width(4)
		self.set_tab_pos(gtk.POS_TOP)
		self.connect("switch-page", self.OnSwitchPage)
		
	def SendMessage(self, user, text = None, direction = None):
		if not self.users.has_key(user):
			tab = PrivateChat(self, user)
			self.users[user] = tab
			

			self.append_page(tab.Main, user[:15], tab.OnClose)

		if direction:
			if self.get_current_page() != self.page_num(self.users[user].Main):
				self.set_current_page(self.page_num(self.users[user].Main))
		if text is not None:
			self.users[user].SendMessage(text)
	
	def ShowMessage(self, direction, user, text):
		if user in self.frame.Networking.config["ignored"]:
			return

		ctcpversion = 0
		if text == "\x01VERSION\x01":
			ctcpversion = 1
			text = "CTCP VERSION"
		self.SendMessage(user, None)
		tab = self.users[user]
		tab.ShowMessage(direction, text)
		#if ctcpversion and self.frame.np.config.sections["server"]["ctcpmsgs"] == 0:
			#self.SendMessage(msg.user, "Nicotine %s" % version)
		#self.request_changed(tab.Main)
		#self.frame.RequestIcon(self.frame.PrivateChatTabLabel)
		#if self.get_current_page() != self.page_num(self.users[msg.user].Main) or self.frame.notebook1.get_current_page() != 1:
			#if msg.user not in self.frame.tray_status["hilites"]["private"]:
				#self.frame.tray_status["hilites"]["private"].append(msg.user)
				#self.frame.SetImage(None)
		self.request_changed(self.users[user].Main)
		
	def OnSwitchPage(self, notebook, page, page_num, force = 0):
		if self.frame.notebook_outside.get_current_page() != 1 and not force:
			return
		page = notebook.get_nth_page(page_num)	
		for name, tab in self.users.items():
			if tab.Main is page:
				gobject.idle_add(tab.ChatLine.grab_focus)
				break
			
	def updateStatus(self, user, status):
		if self.users.has_key(user):
			gobject.idle_add(self.users[user].setStatus)
			
	def RemoveTab(self, tab):
		self.remove_page(self.page_num(tab.Main) )
		del self.users[tab.user]
		tab.Main.destroy()
		
class Searches(IconNotebook):
	def __init__(self, frame):
		IconNotebook.__init__(self, frame.images)
		self.set_scrollable(True)
		self.show()
		
		self.frame = frame
		self.set_border_width(4)
		self.set_tab_pos(gtk.POS_TOP)
		self.connect("switch-page", self.OnSwitchPage)
		
		self.tickets = {}

	def RemoveTab(self, tab):
		self.remove_page(self.page_num(tab.Main) )
		del self.tickets[tab.ticket]
		
	def DoSearch(self, searchtype, query, user=None):
		self.frame.Networking.Search(searchtype, query, user=None)
			
	def OnSwitchPage(self, notebook, page, page_num, force = 0):
		if self.frame.notebook_outside.get_current_page() != 1 and not force:
			return
		page = notebook.get_nth_page(page_num)	
		for name, tab in self.users.items():
			if tab.Main is page:
				gobject.idle_add(tab.Entry.grab_focus)
				break
			
	def NewResults(self, ticket, user, free, speed, queue, results):
		if self.tickets.has_key(ticket):
			self.tickets[ticket].NewResults(user, free, speed, queue, results)
			self.request_changed(self.tickets[ticket].Main)
			
	def NewSearch(self, query, ticket):
		#if str(ticket) not in self.frame.widgets["search"]:
			#self.DoSearch(str(ticket))
		
		if not self.tickets.has_key(ticket):
			tab = Search(self, query, ticket)
			self.tickets[ticket] = tab
			
			self.append_page(self.tickets[ticket].Main, query[:15], tab.OnClose)


	#def SearchFrame(self):
		
		
class Search:
	def __init__(self, searches, query, ticket):
		self.searches = searches
		self.frame = searches.frame
		self.query = str(query)
		self.ticket = ticket
		self.num = 0
		self.selected_results = []
		self.selected_users = []
		
		self.ScrolledWindow =  gtk.ScrolledWindow()
		self.ScrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.ScrolledWindow.show()
		self.ScrolledWindow.set_shadow_type(gtk.SHADOW_IN)
		self.store = gtk.ListStore(int, str, str, str, int, int, str, int, str, str, str, int, int)
		self.treeview = treeview = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		treeview.show()
		treeview.set_headers_visible(True)
		self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		treeview.set_reorderable(True)
		
		cols = InitialiseColumns(treeview,
		["", 30, "text"], # 0
		[_("Filename"), 250, "text"], #1
		[_("User"), 100, "text"], #2
		[_("Size"), 100, "text"], #3
		[_("Speed"), 50, "text"], #4
		[_("Queue"), 50, "text"], #5
		[_("Instant Download"), 20, "text"], #6
		[_("Bitrate"), 50, "text"], #7
		[_("Length"), 50, "text"], #8
		[_("Directory"), 500, "text"], #9
		# Full path 10 
		# size (number) 11
		# length (number) 12
		)
		
		cols[0].set_sort_column_id(0)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(11)
		cols[4].set_sort_column_id(4)
		cols[5].set_sort_column_id(5)
		cols[6].set_sort_column_id(6)
		cols[7].set_sort_column_id(7)
		cols[8].set_sort_column_id(12)
		cols[9].set_sort_column_id(9)

		

		self.popup_menu = popup = PopupMenu(self.frame, "search")
		popup.setup(
			("#" + _("Download _File"), self.OnDownloadSelected, gtk.STOCK_GO_DOWN),
			("#" + _("_Download Directory"), popup.OnDownloadDirectory, gtk.STOCK_GO_DOWN),
			("", None),
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Reload _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		treeview.connect("button_press_event", self.OnMouseClicked)
					
		self.ScrolledWindow.add(treeview)
		
		self.Main = self.ScrolledWindow

	def OnClose(self, widget):

		self.searches.RemoveTab(self)
		self.Main.destroy()
		
	def NewResults(self, user, free, speed, queue, results):
		try:
			
			
			Store = self.store
			treeview = self.treeview
			num = self.num
			if free == 1:
				free = "Y"
			else:
				free = "N"
			for files in results:
				num += 1
				dire = ''
				size = self.frame.Humanize( files[1])
				for path in files[0].split("\\")[:-1]:
					dire += path+"\\"
				if files[3] == []:
					bitrate = 0
					time = "0:00"
					length = 0
				else:
					bitrate = files[3][0]
					time = self.frame.Length2Time(files[3][1])
					length = files[3][1]
				
				self.store.append([ num, files[0].split("\\")[-1], user, size, speed, queue,free,  bitrate, time, dire , files[0], files[1], length ])

 			self.num = num

				
		except Exception, e:
			print "ERROR: DoSearchResults: ", e

	def SelectedResultsCallback(self, model, path, iter):
		user = model.get_value(iter, 2)
		fn = model.get_value(iter, 10)
		
		self.selected_results.append((user, fn))
		
		if not user in self.selected_users:
			self.selected_users.append(user)
			
	def OnDownloadSelected(self, widget):
		if DEBUG: print self.selected_results

		for file in self.selected_results:
			self.frame.Networking.DownloadFile(file[0], file[1])
			
	def OnMouseClicked(self, widget, event):
		if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
			self.selected_results = []
			self.selected_users = []
			self.treeview.get_selection().selected_foreach(self.SelectedResultsCallback)
			self.OnDownloadSelected(widget)
			self.treeview.get_selection().unselect_all();
			return True
		
		elif event.button == 3:
			return self.OnPopupMenu(widget, event)
		return False
	
	def OnPopupMenu(self, widget, event):
		
		self.selected_results = []
		self.selected_users = []
		self.treeview.get_selection().selected_foreach(self.SelectedResultsCallback)
		
		items = self.popup_menu.get_children()
		#print items
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		
		if not d:
			return
		path, column, x, y = d
		user =  self.store.get_value(self.store.get_iter(path), 2)
		file = self.store.get_value(self.store.get_iter(path), 10)
		self.popup_menu.set_user(user)
		self.popup_menu.set_path(file)
		num = 8
		
		self.popup_menu.set_user(user)
		#items[5].set_active(user in self.Networking.config["buddies"].keys())
		#if string is not "search":
		if self.frame.Networking.config != {}:
			items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
			items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
			items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
			items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)
		return True # Don't select files
		

class TrayApp:
	def __init__(self, frame):
		self.t = None
		self.frame = frame
		self.is_mapped = 1
		self.current_image = None
		
	def trayapp(self, string):
		if trayicon_load == 0:
			return
		
		self.is_mapped = 1
		if self.t == None:
			self.t = trayicon.TrayIcon("Murmur")
			self.eventbox = gtk.EventBox()
			self.TrayMenu()
			if DEBUG == True: print "Status:", self.frame.status
			if self.frame.status:
				message = _("Connected to Museek: %s Status: Away" % self.frame.username)
				self.SetToolTip( message)
				self.frame.update_statusbar( message)
				
				self.SetImage("yellow")
			elif self.frame.status == 0:
				message = _("Connected to Museek: %s Status: Online" % self.frame.username)
				self.SetToolTip( message )
				self.frame.update_statusbar( message )
				self.SetImage("green")
			else:
				self.SetImage("red")
			self.eventbox_closed = "no"
			self.t.add(self.eventbox)
			self.t.show_all()
			
		else:
			self.t.hide()
			self.eventbox.hide()
			self.t = None
			self.eventbox = None
			self.eventbox_closed = "yes"
		self.tooltips = gtk.Tooltips()
		#self.tooltips.set_delay(1500)

		
	def OnTrayiconServer(self, widget):
		items = self.tray_popup_menu_server.get_children()
		
		
		if self.current_image_name == "red":
			items[0].set_sensitive(True)
			items[1].set_sensitive(False)
		else:
			items[0].set_sensitive(False)
			items[1].set_sensitive(True)
		return
			
	def HideUnhideWindow(self, widget):
		if self.is_mapped:
			self.frame.MurmurWindow.unmap()
			self.is_mapped = 0
		else:
			self.frame.MurmurWindow.map()
			self.frame.MurmurWindow.grab_focus()
			self.is_mapped = 1
			
	def TrayMenu(self):
		try:
			self.tray_popup_menu_server= popup0 = PopupMenu(self.frame, "")
			popup0.setup(
				("#" + _("_Connect"), self.frame.connect_process, gtk.STOCK_CONNECT),
				("#" + _("_Disconnect"), self.frame.disconnect, gtk.STOCK_DISCONNECT),
			)
			self.tray_popup_menu = popup = PopupMenu(self.frame, "")
			popup.setup(
				("#" + _("Hide / Unhide Murmur"), self.HideUnhideWindow, gtk.STOCK_GOTO_BOTTOM),
				(1, _("Server"), popup0, self.OnTrayiconServer),
				("#" + _("Settings"), self.frame.SettingsWindow, gtk.STOCK_PREFERENCES),
				("#" + _("Lookup a User's IP"), self.frame.LookupIP, gtk.STOCK_NETWORK),
				("#" + _("Lookup a User's Info"), self.frame.LookupUserInfo, gtk.STOCK_DIALOG_INFO),
				("#" + _("Lookup a User's Shares"), self.frame.LookupUserShares, gtk.STOCK_HARDDISK),
				("%" + _("Toggle Away"), self.frame.away_toggle, self.frame.images["away"] ),
				("#" + _("Quit"), self.frame.quit, gtk.STOCK_QUIT),
			)

			self.eventbox.connect_object("button_press_event", self.OnTrayiconClicked, popup)

			
		except Exception, e:
			if DEBUG == True: print "menu error", e
		

		
	def OnTrayiconClicked(self, widget, event):
		try:
			if event.type == gtk.gdk.BUTTON_PRESS:
				if event.button == 1:
					self.HideUnhideWindow(None)
				else:
					items = self.tray_popup_menu.get_children()
					if self.current_image_name == "red":
						items[3].set_sensitive(False)
						items[4].set_sensitive(False)
						items[5].set_sensitive(False)
						items[6].set_sensitive(False)
					else:
						
						items[3].set_sensitive(True)
						items[4].set_sensitive(True)
						items[5].set_sensitive(True)
						items[6].set_sensitive(True)
					widget.popup(None, None, None, event.button, event.time)
					# Tell calling code that we have handled this event the buck
					# stops here.
					return True
				# Tell calling code that we have not handled this event pass it on.
			return False
		except Exception,e:
			if DEBUG == True: print "button_press error", e
	
	def SetImage(self, image):
		try:
			if self.t == None:
				return

			self.eventbox.hide()
			
			if self.current_image != None and self.eventbox_closed == "no":
				self.eventbox.remove(self.current_image)
				
			self.current_image_name = image
			image1 = gtk.Image()
			image1.set_from_pixbuf(self.frame.images[image])
			image1.show()
			self.current_image = image1

			self.eventbox.add(self.current_image)
			self.eventbox.show()
		
		except Exception,e:
			if DEBUG == True: print "Error in SetImage", e
			
	def SetToolTip(self, message):
		try:
			#gtk.gdk.threads_enter()
			if self.frame.Config["murmur"]["tooltips"] == "yes":
				self.tooltips.set_tip(self.eventbox, message) 
			#gtk.gdk.threads_leave()
		except Exception,e:
			if DEBUG == True: print "SetToolTip ERROR", e
			

class ChatRoom:
	
	def __init__(self, chatrooms, room, users):
		self.lines = []
		self.chatrooms = chatrooms
		self.frame = chatrooms.frame
		self.room = room
		self.leaving = 0
		
		self.textbuffer = gtk.TextBuffer()
		self.chatview = gtk.TextView(buffer=self.textbuffer)
		self.chatview.set_editable(False)
		self.chatview.set_wrap_mode( gtk.WRAP_WORD)
		self.chatview.set_cursor_visible(False)
		self.chatview.show()
		
		self.chatScroll = gtk.ScrolledWindow()
		self.chatScroll.set_border_width(1)
		self.chatScroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.chatScroll.set_shadow_type(gtk.SHADOW_IN)
		self.chatScroll.add(self.chatview)
		self.chatScroll.show()
		
		self.chatEntry = gtk.Entry()
		self.chatEntry.set_text("")
		
		self.chatEntry.connect("activate", self.ChatEnter, self.chatEntry, "chat")
		self.chatEntry.connect("key_press_event", self.OnKeyPress)
		self.chatEntry.show()
		# Containing box with scrolled window and text input box
		self.vbox = gtk.VBox(spacing=3)
		self.vbox.set_border_width(3)
		self.vbox.pack_start(self.chatScroll, True, True, 0)
		self.vbox.pack_end(self.chatEntry, False, False, 0)
		self.vbox.show()
		
		
		
		self.statusbuffer = gtk.TextBuffer()
		
		self.RoomLog = gtk.TextView(buffer=self.statusbuffer)
		
		self.RoomLog.set_editable(False)
		self.RoomLog.set_wrap_mode( gtk.WRAP_NONE)
		self.RoomLog.set_cursor_visible(False)
		self.RoomLog.show()
		
		self.status_scroll = gtk.ScrolledWindow()
		self.status_scroll.set_border_width(1)
		self.status_scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.status_scroll.set_shadow_type(gtk.SHADOW_IN)
		self.status_scroll.add(self.RoomLog)
		self.status_scroll.show()
		

		
		self.usersmodel = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, int )
		self.UserList = gtk.TreeView(self.usersmodel)
		self.UserList.set_property("rules-hint", True)
		# Users-in-room Listbox with users and files
		
		cols = InitialiseColumns(self.UserList, 
			["", -1, "pixbuf"], #0
			[_("Username"), 100, "text"], #1
			[_("Files"), 0, "text"], #2
			[_("Speed"), 0, "text"], #3
		)
		
		cols[0].set_sort_column_id(4)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		
		self.users = {}
		for user in users.keys():
			img = self.frame.GetStatusImage(user, users[user][0]) 
			hspeed = Humanize(users[user][1])
			hfiles = Humanize(users[user][3])
			iter = self.usersmodel.append([img, str(user), hfiles, hspeed, users[user][0] ] )
			self.users[user] = iter
		self.usersmodel.set_sort_column_id(1, gtk.SORT_ASCENDING)
		
		self.popup_menu = popup = PopupMenu(self.frame, "chat")
		popup.setup(
			("#" + _("Private _Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("Show IP address"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Get user info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("Browse files"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		self.UserList.connect("button_press_event", self.OnPopupMenuRoom, "chat", "")
		self.UserList.show()
		
		# Scrollwindow containing Users-in-room Listbox
		self.UserList_scroll = gtk.ScrolledWindow()
		self.UserList_scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.UserList_scroll.add(self.UserList)
		self.UserList_scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		self.UserList_scroll.show()
		
		autojoin_check = gtk.CheckButton(label="Autojoin")
		if "autojoin" in self.frame.Networking.config.keys():
			if room in self.frame.Networking.config["autojoin"].keys():
				autojoin_check.set_active(True)
			else:
				autojoin_check.set_active(False)
		else:
			autojoin_check.set_active(False)
		autojoin_check.connect("toggled", self.autojoin_check, "check button 1")	
		autojoin_check.show()
		
		self.Leave = self.frame.CreateIconButton(gtk.STOCK_CLOSE, "stock", self.OnLeave, _("Leave Room"))

		over_button = gtk.HBox(spacing=3)
		over_button.set_border_width(3)
		over_button.pack_start(autojoin_check, True, True, 0)
		over_button.pack_end(self.Leave, False, False, 1)
		over_button.show()

		userlist_over_button = gtk.VBox(spacing=0)
		userlist_over_button.set_border_width(0)
		userlist_over_button.pack_start(self.UserList_scroll, True, True, 0)
		userlist_over_button.pack_end(over_button, False, False, 1)
		userlist_over_button.show()
		
		# Pane that contains the Statusbox and Chatroom
		self.vpane = gtk.VPaned()
		self.vpane.pack1(self.status_scroll, False, True)
		self.vpane.pack2(self.vbox, True, False)
		self.vpane.show()
		
		# Pane that contains the Statusbox+Chatroom and Listbox
		self.Main = gtk.HPaned()
		self.Main.pack1(self.vpane, True, True)
		self.Main.pack2(userlist_over_button, False, True)
		self.Main.show()

		
		self.chatEntry.grab_focus()
		self.vbox.set_focus_child(self.chatEntry)
		
		self.UpdateColours()

	def autojoin_check(self, widget, string):
		
		if not self.frame.Networking.config.has_key("autojoin"):
			return
		if self.room in self.frame.Networking.config["autojoin"].keys():
			self.frame.Networking.mod_config("unautojoin", self.room)
		else:
			self.frame.Networking.mod_config("autojoin", self.room)
			
	def Rejoined(self, users):
		for user in users.keys():
			if self.users.has_key(user):
				self.usersmodel.remove(self.users[user])
			img = self.frame.GetStatusImage(user, users[user][0])
			hspeed = Humanize(users[user][1])
			hfiles = Humanize(users[user][3])
			iter = self.usersmodel.append([img, str(user), hfiles, hspeed, users[user][0] ] ) 
			self.users[user] = iter

		AppendLine(self.chatview, _("--- reconnected ---"), None)

	def destroy(self):
		self.Main.destroy()
		
	def ChatEnter(self, something, entry, mtype):

		text = entry.get_text()
		result = None
		#result = expand_alias(self.frame.np.config.aliases, text)
		if result is not None:
			text = result
		if not text:
			widget.set_text("")
			return
			
		s = text.split(" ", 1)
		cmd = s[0]
		if len(s) == 2 and s[1]:
			realargs = args = s[1]
		else:
			args = "" #self.user
			realargs = ""
			
		if text == "":
			return
		if cmd in ["/w", "/whois", "/info"]:
			if args:
				self.frame.GetUserInfo(args)
				self.frame.OnUserInfo(None)
		elif cmd in ["/b", "/browse"]:
			if args:
				self.frame.GetShares(args)
				self.frame.OnUserShares(None)
		elif cmd == "/ip":
			if args:
				if args not in self.frame.ip_requested:
					self.frame.ip_requested.append(args)
					self.frame.Networking.PeerAddress(args)
		elif cmd == "/nsa":
			if args:
				self.frame.GetUserInfo(args)
				self.frame.GetShares(args)
				self.frame.OnUserInfo(None)
				
		elif cmd == "/reload":
			self.frame.Networking.ReloadShares()
			
		elif cmd == "/pm":
			if realargs:
				self.frame.PrivateChats.SendMessage(realargs, None, 1)
		elif cmd in ["/m", "/msg"]:
			if realargs:
				s = realargs.split(" ", 1)
				user = s[0]
				if len(s) == 2:
					msg = s[1]
				else:
					msg = None
				self.frame.PrivateChats.SendMessage(user, msg)
		elif cmd in ["/s", "/search"]:
			if realargs:
				self.frame.Networking.Search(0, realargs)
				self.frame.OnSearch(None)
		elif cmd in ["/us", "/usearch"]:
			s = args.split(" ", 1)
			if len(s) == 2:
				self.frame.Networking.Search(3, s[1], s[0])
				self.frame.OnSearch(None)
			else:
				return
			#if realargs:
				##self.frame.Searches.user = self.user
				#self.frame.Searches.DoSearch(3, realargs)
				#self.frame.OnSearch(None)
		elif cmd in ["/rs", "/rsearch"]:
			if realargs:
				self.frame.Networking.Search(2, realargs)
				self.frame.OnSearch(None)
		elif cmd in ["/bs", "/bsearch"]:
			if realargs:
				self.frame.Networking.Search(1, realargs)
				self.frame.OnSearch(None)
		elif cmd in ["/ad", "/add", "/buddy"]:
			if args:
				self.frame.Networking.mod_config("buddy", args)
		elif cmd in ["/rem", "/unbuddy"]:
			if args:
				self.frame.Networking.mod_config("unbuddy", args)
		elif cmd == "/ban":
			if args:
				self.frame.Networking.mod_config("ban", args)
		elif cmd == "/unban":
			if args:
				self.frame.Networking.mod_config("unban", args)
		elif cmd == "/ignore":
			if args:
				self.frame.Networking.mod_config("ignore", args)
		elif cmd == "/unignore":
			if args:
				self.frame.Networking.mod_config("unignore", args)
		elif cmd == "/trust":
			if args:
				self.frame.Networking.mod_config("trust", args)
		elif cmd == "/distrust":
			if args:
				self.frame.Networking.mod_config("distrust", args)
		elif cmd == "/ctcpversion":
			if args:
				self.frame.Networking.PrivateMessage(0, args, "\x01VERSION\x01")
			
		elif cmd in ["/clear", "/cl"]:
			self.chatview.get_buffer().set_text("")
		elif cmd in ["/a", "/away"]:
			
			self.frame.away_toggle(None)
		elif cmd in ["/q", "/quit"]:
			self.frame.window_quit(None)
		elif cmd in ["/c", "/close", "/l", "/leave", "/part", "/p"]:
			self.OnLeave(None)
		elif cmd == "/updatenormal":
			self.frame.Muscan.UpdateNormal()
		elif cmd == "/updatebuddy":
			self.frame.Muscan.UpdateBuddy()
		elif cmd == "/rescan":
			self.frame.Muscan.RescanNormal()
			self.frame.Muscan.RescanBuddy()
		elif cmd == "/rescannormal":
			self.frame.Muscan.RescanNormal()
		elif cmd == "/rescanbuddy":
			self.frame.Muscan.RescanBuddy()
		
		elif cmd == "/addnormaldir":
			if args:
				self.frame.Muscan.AddNormalDirectory(args)
			else:
				return
		elif cmd == "/removenormaldir":
			if args:
				self.frame.Muscan.RemoveNormalDirectory(args)
			else:
				return
		elif cmd == "/addbuddydir":
			if args:
				self.frame.Muscan.AddBuddyDirectory(args)
			else:
				return
		elif cmd == "/removebuddydir":
			if args:
				self.frame.Muscan.RemoveBuddyDirectory(args)
			else:
				return
		elif cmd == "/listshares":
			self.frame.Muscan.ListNormal()
			self.frame.Muscan.ListBuddy()
		elif cmd == "/listnormal":
			self.frame.Muscan.ListNormal()
		elif cmd == "/listbuddy":
			self.frame.Muscan.ListBuddy()
			
		elif cmd and cmd[:1] == "/" and cmd != "/me" and cmd[:2] != "//":
			self.frame.AppendToLogWindow(_("Command %s is not recognized") % text)
			return
		else:
			if text[:2] == "//":
				text = text[1:]

			self.frame.Networking.SayRoom(self.room, text)
		entry.set_text("")
		

				
	COMMANDS = ["/alias ", "/unalias ", "/whois ", "/browse ", "/ip ", "/pm ", "/msg ", "/search ", "/usearch ", "/rsearch ", "/bsearch ", "/join ", "/leave", "/add ", "/buddy ", "/unbuddy ", "/ban ", "/ignore ", "/unban ", "/unignore ", "/clear", "/part ", "/quit", "/rescan", "/tick", "/nsa", "/info", "/ctcpversion", "/rem ", "/cl", "/t", "/a", "/q", "/l", "/p", "/bs", "/rs", "/us", "/s", "/m", "/w", "/al", "/un", "/w", "/updatenormal", "/updatebuddy", "/rescannormal", "/rescanbuddy", "/addnormaldir", "/addbuddydir", "/removenormaldir", "/removebuddydir", "/listshares", "/listnormal", "/listbuddy" ]
		
	def SayInChatRoom(self, user, line):
		if len(self.lines) >= 400:
			buffer = self.chatview.get_buffer()
			start = buffer.get_start_iter()
			end = buffer.get_iter_at_line(self.lines[200])
			self.chatview.get_buffer().delete(start, end)
			del self.lines[0:200]
		if line[0] == "/" and line[1] != "/" and line[:4] != "/me ":
			# Do Command
			c = line.split(" ", 1)
			command = c[0]
			if len(c) == 2:
				args = c[1]
			else:
				args = ""
			#print "command", command, "args", args
		else:
			# Say
			if line[:4] == "/me ":
				message = "* %s %s"  % (user, line[4:])
			else:
				message = "[%s] %s" % (user, line)
		
			message = "\n-- ".join(message.split("\n"))

			self.lines.append(AppendLine(self.chatview, message, None, username=user, usertag=self.tag_users[user]))
		if user != self.frame.username and self.frame.username in message:
				self.chatrooms.request_hilite(self.Main)
		else:
			self.chatrooms.request_changed(self.Main)
		#if self.Log.get_active():
			#self.logfile = WriteLog(self.logfile, self.frame.np.config.sections["logging"]["logsdir"], self.room, line)
	def OnKeyPress(self, widget, event):
		if event.keyval == gtk.gdk.keyval_from_name("Prior"):
			scrolled = self.chatview.get_parent()
			adj = scrolled.get_vadjustment()
			adj.set_value(adj.value - adj.page_increment)
		elif event.keyval == gtk.gdk.keyval_from_name("Next"):
			scrolled = self.chatview.get_parent()
			adj = scrolled.get_vadjustment()
			max = adj.upper - adj.page_size
			new = adj.value + adj.page_increment
			if new > max:
				new = max
			adj.set_value(new)
			
		## Tab Completion
		if event.keyval != gtk.gdk.keyval_from_name("Tab"):
			return False
		ix = widget.get_position()
		text = widget.get_text()[:ix].split(" ")[-1]
		list = self.users.keys() + [i for i in self.frame.Networking.config["buddies"] ] + ["murmur"]
		if ix == len(text) and text[:1] == "/":
			list +=  self.COMMANDS
			#["/"+k for k in self.frame.np.config.aliases.keys()] +
		completion, single = self.frame.GetCompletion(text, list)
		if completion:
			if single:
				if ix == len(text) and text[:1] != "/":
					completion += ": "
			widget.insert_text(completion, ix)
			widget.set_position(ix + len(completion))
		widget.emit_stop_by_name("key_press_event")
		return True
	def UserJoinedRoom(self, username):
		if self.users.has_key(username):
			return
		status, speed, downloads, files, dirs, exists = self.frame.user_stats[username]
		AppendLine(self.RoomLog, _("%s joined the room") % username, None)
		img = self.frame.GetStatusImage(username, status)
		hspeed = Humanize(speed)
		hfiles = Humanize(files)
		iter = self.usersmodel.append([img, username, hfiles, hspeed, status])
		self.users[username] = iter
		color = self.getUserStatusColor(status)
		if username in self.tag_users.keys():
			self.changecolour(self.tag_users[username], color)
		else:
			self.tag_users[username] = self.makecolour(self.chatview.get_buffer(), color, username=username)
	
	def UserLeftRoom(self, username):
		if not self.users.has_key(username):
			return
		AppendLine(self.RoomLog, _("%s left the room") % username, None)
		self.usersmodel.remove(self.users[username])
		del self.users[username]
		if username in self.tag_users.keys():
			color = self.getUserStatusColor(-1)
			self.changecolour(self.tag_users[username], color)
		
	def GetListStatus(self, user):
		status = self.usersmodel.get_value(self.users[user], 4)
		img = self.frame.GetStatusImage(user, status)
		self.usersmodel.set(self.users[user], 0, img, 4, status)
		
	def GetUserStats(self, user, speed, files):
		if not self.users.has_key(user):
			return
		hspeed = Humanize(speed)
		hfiles = Humanize(files)
		self.usersmodel.set(self.users[user], 2, hfiles, 3, hspeed)

	def GetUserStatus(self, user, status):
		if not self.users.has_key(user):
			return

                if status != self.usersmodel.get_value(self.users[user], 4):
                        img = self.frame.GetStatusImage(user, status)
			if status == 1:
				action = _("%s has gone away")
			else:
				action = _("%s has returned")
			AppendLine(self.RoomLog, action % user, None)
			if user in self.tag_users.keys():
				color = self.getUserStatusColor(status)
				self.changecolour(self.tag_users[user], color)
			self.usersmodel.set(self.users[user], 0, img, 4, status)

	def makecolour(self, buffer, colour, username=None):
		colour = self.frame.Config["colors"][colour]
		font =  self.frame.Config["colors"]["chatfont"]
		if colour:
			tag = buffer.create_tag(foreground = colour, font=font)
		else:
			tag = buffer.create_tag( font=font)
		if username is not None:

			#tag.set_property("underline", pango.UNDERLINE_SINGLE)
			tag.set_property("weight",  pango.WEIGHT_BOLD)
			tag.connect("event", self.UserNameEvent, username)
			tag.last_event_type = -1
			#tag = buffer.create_tag( font=font)
		return tag
		
	def UserNameEvent(self, tag, widget, event, iter, user):
		if tag.last_event_type == gtk.gdk.BUTTON_PRESS and event.type == gtk.gdk.BUTTON_RELEASE and event.button == 1:
			if user in self.users.keys():
				self.popup_menu.set_user(user)
				items = self.popup_menu.get_children()
				# Chat, Userlists use the normal popup system
				num = 5
				items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
				items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
				items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
				items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))
				self.popup_menu.popup(None, None, None, event.button, event.time)
		tag.last_event_type = event.type
		
	def UpdateColours(self):
		
				
		buffer = self.chatview.get_buffer()
		self.tag_remote = self.makecolour(buffer, "chatremote")
		self.tag_local = self.makecolour(buffer, "chatlocal")
		self.tag_me = self.makecolour(buffer, "chatme")
		self.tag_hilite = self.makecolour(buffer, "chathilite")
		self.tag_users = {}
		for user in self.users:
			status = self.usersmodel.get_value(self.users[user], 4)
			color = self.getUserStatusColor(status)
			self.tag_users[user] = self.makecolour(buffer, color, user)

		buffer = self.RoomLog.get_buffer()
		self.tag_log = self.makecolour(buffer, "chatremote")
		
	def getUserStatusColor(self, status):
		if status == 1:
			color = "useraway"
		elif status == 2:
			color = "useronline"
		else:
			color = "useroffline"
		return color
	
	def changecolour(self, tag, colour):
		if self.frame.Config["colors"].has_key(colour):
			color = self.frame.Config["colors"][colour]
		else:
			color = ""
		font = self.frame.Config["colors"]["chatfont"]
		
		if color:
			tag.set_property("foreground", color)
			tag.set_property("font", font)
			if colour in ["useraway", "useronline", "useroffline"]:
				tag.set_property("weight",  pango.WEIGHT_BOLD)
		else:
			tag.set_property("font", font)
			
	def ChangeColours(self):
		
				
		self.changecolour(self.tag_remote, "chatremote")
		self.changecolour(self.tag_local, "chatlocal")
		self.changecolour(self.tag_me, "chatme")
		self.changecolour(self.tag_hilite, "chathilite")
		#self.changecolour(self.tag_username, color)
		#self.setStatus()
		
	def OnPopupMenuRoom(self, widget, event, string, string2):
		if event.button != 3:
			return
		items = self.popup_menu.get_children()
		#if DEBUG == True: print string
		# Chat, Userlists use the normal popup system
		num = 5
		if string == "chat":
			
			room = self.room
			if DEBUG == True:  print "-- Popup -- Room:", string
		
			d = self.UserList.get_path_at_pos(int(event.x), int(event.y))
			if not d:
				return
			path, column, x, y = d
			user =  self.usersmodel.get_value(self.usersmodel.get_iter(path), 1)
				
		self.popup_menu.set_user(user)
		items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)

	def OnLeave(self, widget = None):
		if self.leaving:
			return
		if self.room in self.chatrooms.joinedrooms:
			self.frame.Networking.LeaveRoom(self.room)
		self.Leave.set_sensitive(False)
		self.leaving = 1
		if self.room in self.frame.Config["logging"]["rooms"]:
			self.frame.Config["logging"]["rooms"].remove(self.room)
		
	def ConnClose(self):
		self.usersmodel.clear()
		self.users = {}
		AppendLine(self.chatview, _("--- disconnected from museek daemon ---"), None)
		



class ChatRooms(IconNotebook):
	
	def __init__(self, frame):
		
		IconNotebook.__init__(self, frame.images)
		self.popup_enable()
		self.frame = frame
		
		self.joinedrooms = {}
		self.rooms = {}
		self.autojoin = 1
		
		self.CreateRoomList()
		
		self.set_tab_pos(gtk.POS_TOP)
		self.set_scrollable(True)
		self.show()
		self.connect("switch-page", self.OnSwitchPage)
	
		
	#def ConnClose(self):
		#self.roomsmaster.ConnClose()
		
	def OnSwitchPage(self, notebook, page, page_num, force = 0):
		if self.frame.notebook_outside.get_current_page() != 0 and not force:
			return
		page = notebook.get_nth_page(page_num)	
		for name, tab in self.joinedrooms.items():
			if tab.Main is page:
				gobject.idle_add(tab.chatEntry.grab_focus)
				break

		#self.frame = frame
		
	def CreateRoomList(self):
		label = gtk.Label(_("Join room:") )
		label.show()
		
		self.entry = gtk.Entry()
		self.entry.set_text("")
		self.entry.grab_focus()
		self.entry.show()
		self.entry.connect("activate", self.EnterRoom, self.entry)
		
		#self.refresh_button = gtk.Button(_("Refresh List") )
		#self.refresh_button.connect_object("clicked", self.OnPopupRefresh, "")
		#self.refresh_button.show()
		self.refresh_button = self.frame.CreateIconButton(gtk.STOCK_REFRESH, "stock", self.OnPopupRefresh, _("Refresh List"))
		
		addhbox = gtk.HBox(spacing=3)
		addhbox.set_border_width(3)
		addhbox.pack_start(label, False, False, 0)
		addhbox.pack_start(self.entry, True, True,  0)
		addhbox.pack_end(self.refresh_button, False, False,  0)
		addhbox.show()
		
		self.store = gtk.ListStore( int, str )

		# Users-in-room Listbox with users and files
		self.treeview  = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		RoomSize = gtk.TreeViewColumn('Size')
		cell = gtk.CellRendererText()
		RoomSize.pack_start(cell, True)
		RoomSize.add_attribute(cell, 'text', 0)
		RoomSize.set_sort_column_id(0)
		RoomSize.set_resizable(True)

		RoomName = gtk.TreeViewColumn(_('Room Name'))
		cell = gtk.CellRendererText()
		RoomName.pack_start(cell, True)
		RoomName.add_attribute(cell, 'text', 1)
		RoomName.set_sort_column_id(1)
		RoomName.set_resizable(True)
		
		#self.treeview.set_search_column(0)
		self.treeview.set_search_column(1)
		
		
		self.treeview.append_column(RoomSize)
		self.treeview.append_column(RoomName)

		
		#self.store.set_sort_column_id(0, gtk.SORT_DESCENDING)
		
		self.popup_menu = popup = PopupMenu(self.frame, "rooms")
		popup.setup(
			("#" + _("_Join Room"), popup.OnJoinRoom, gtk.STOCK_JUMP_TO),
			("#" + _("_Leave Room"), popup.OnLeaveRoom, gtk.STOCK_CLOSE),
					)
		self.treeview.connect("button_press_event", self.OnPopupMenuRoomList)
		self.treeview.show()
		
		# Scrollwindow containing Users-in-room Listbox
		widget = gtk.ScrolledWindow()
		widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		widget.add(self.treeview)
		widget.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		
		widget.show()
		
		# Containing box with scrolled window and text input box
		self.Main = gtk.VBox(spacing=3)
		self.Main.set_border_width(3)
		self.Main.pack_start(widget, True, True, 0)
		self.Main.pack_end(addhbox, False, False, 0)
		self.Main.show()

		self.frame.notebook_roomlist.add(self.Main)
		
		
	def EnterRoom(self, widget, event):
		room = self.entry.get_text()
		if room == "":
			return
		self.JoinARoom(room)
		self.entry.set_text("")
	
	def JoinARoom(self, room):
		if room != None and room != "":
			self.frame.Networking.JoinRoom(room)
		
	def UpdateRoomList(self, rooms):
		if DEBUG == True: print "UpdateRoomList"
		self.store.clear()
		self.rooms.clear()
		# Vastly speed up/Do not sort
		self.store.set_default_sort_func(lambda *args: -1) 
  		self.store.set_sort_column_id(-1, gtk.SORT_ASCENDING)
		self.treeview.freeze_child_notify()
		
		for room, sizes in rooms.items():
			self.rooms[room] = self.store.append([ sizes, room] )
		# Back to normal/Sort Descending
		self.treeview.thaw_child_notify()
		self.store.set_sort_column_id(0, gtk.SORT_DESCENDING)
		
	def OnResort(self, column, column_id):
		if self.roomsmodel.sort_col == column_id:
			order = self.roomsmodel.sort_order
			if order == gtk.SORT_ASCENDING:
				order = gtk.SORT_DESCENDING
			else:
				order = gtk.SORT_ASCENDING
			column.set_sort_order(order)
			self.roomsmodel.sort_order = order
			self.frame.roomlist.RoomsList.set_model(None)
			self.roomsmodel.sort()
			self.frame.roomlist.RoomsList.set_model(self.roomsmodel)
			return
		cols = self.frame.roomlist.RoomsList.get_columns()
		cols[column_id].set_sort_indicator(True)
		cols[self.roomsmodel.sort_col].set_sort_indicator(False)
		self.roomsmodel.sort_col = column_id
		self.OnResort(column, column_id)
		
	def OnListClicked(self, widget, event):
		if self.roomsmodel is None:
			return False
		if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
			d = self.frame.roomlist.RoomsList.get_path_at_pos(int(event.x), int(event.y))
			if d:
				path, column, x, y = d
				room = self.roomsmodel.get_value(self.roomsmodel.get_iter(path), 0)

			return True
		elif event.button == 3:
			return self.OnPopupMenuRoomList(widget, event)
		return False
		
	def OnPopupMenuRoomList(self, widget, event):
		if event.button != 3 or self.store is None:
			return
		items = self.popup_menu.get_children()
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if d:
			path, column, x, y = d
			room = self.store.get_value(self.store.get_iter(path), 1)

			if room in self.joinedrooms.keys():
				act = (False, True)
			else:
				act = (True, False)
		else:
			room = None
			act = (False, False)
		self.popup_menu.set_user(room)
		items[0].set_sensitive(act[0])
		items[1].set_sensitive(act[1])
		self.popup_menu.popup(None, None, None, event.button, event.time)

	def OnPopupRefresh(self, widget):
		self.frame.Networking.RoomList()
		
	def SayChatRoom(self, room, user, text):
		if user in self.frame.Networking.config["ignored"].keys():
			return
		self.joinedrooms[room].SayInChatRoom(user, text)

	
	def JoinRoom(self, room, users):
		if self.joinedrooms.has_key(room):
			self.joinedrooms[room].Rejoined(users)
			return
		
		for user, stats in users.items():
			#print stats
			self.frame.user_stats[user] = [stats[0], stats[1], stats[2 ], stats[3], stats[4], 1] 
			# online status, avgspeed, numdownloads, numfiles, numdirs
		if self.frame.Config["logging"]["logrooms"] == "yes" and room not in self.frame.Config["logging"]["rooms"]:
			self.frame.Config["logging"]["rooms"].append(room)
		tab = ChatRoom(self, room, users)
		self.joinedrooms[room] = tab
		#chatlabel = gtk.Label(room) 
		#chatlabel.show()
		self.frame.ChatRooms.append_page(tab.Main, room, tab.OnLeave)
		#self.frame.ChatRooms.append_page(tab.Main, chatlabel)

				
	def GetUserStats(self, user, avgspeed, files):
		for room in self.joinedrooms.values():
                        if user in room.users.keys():
			     room.GetUserStats(user, avgspeed, files)
	
	def GetUserStatus(self, user, status):
		for room in self.joinedrooms.values():
                        if user in room.users.keys():
			     gobject.idle_add(room.GetUserStatus, user, status)
			     
	def GetListStatus(self, user):
		for room in self.joinedrooms.values():
                        if room.users.has_key(user):
			     gobject.idle_add(room.GetListStatus, user)
			
	def UserJoinedRoom(self, room, username):
		if self.joinedrooms.has_key(room):
			self.joinedrooms[room].UserJoinedRoom(username)
	
	def UserLeftRoom(self, room, username):
		self.joinedrooms[room].UserLeftRoom(username)
	
	def TickerSet(self, msg):
		self.joinedrooms[msg.room].TickerSet(msg)

	def TickerAdd(self, msg):
		self.joinedrooms[msg.room].TickerAdd(msg)

	def TickerRemove(self, msg):
		self.joinedrooms[msg.room].TickerRemove(msg)

	def UpdateColours(self):
		for room in self.joinedrooms.values():
			room.UpdateColours()

	def LeaveRoom(self, room):
		roomwidget = self.joinedrooms[room]
		#if room.logfile is not None:
			#room.logfile.close()
			#room.logfile = None
		page_num = self.frame.ChatRooms.page_num( roomwidget.Main)

		self.frame.ChatRooms.remove_page(page_num)
		roomwidget.destroy()
		del self.joinedrooms[room]
	
	def ConnClose(self):
		self.roomsmodel = None
		#self.frame.roomlist.RoomsList.set_model(None)
		for room in self.joinedrooms.values():
			room.ConnClose()
		self.autojoin = 1
		
class Logging:
	def __init__(self, frame):
		self.frame = frame
	
	def ChatRoomLog(self, room, user, message):
		
		if room not in self.frame.Config["logging"]["rooms"]:
			return
		text = "[%s]\t%s" % (user, message)
		self.FileLog("rooms", time.strftime("%d %b %Y %H:%M:%S"), room, text )

	def FileLog(self, messagetype, timestamp, place, message):
		try:
			if '/' in place:
				place = place.replace("/", "\\")
			path = os.path.join(os.path.expanduser(self.frame.Config["logging"]["log_dir"]), messagetype, place)
			dir = os.path.split(path)[0]
			try:
				if not os.path.isdir(dir):
					os.makedirs(dir)
				f = open(path, "a")
				## replace inline newlines to preserve formatting
				message.replace("\n","\\n")
				f.write("%s %s\n" % (timestamp, message))
				f.close()
			except:
				print  "Cannot write to file %s, check permissions" % path
		except Exception, e:
			print "FileLog: " + str(e)

class Downloads:
	def __init__(self, frame):
		self.frame = frame
		self.downloads = {}
		self.states = {0: "Finished", 1: "Transferring", 2: "Negotiating", 3:"Waiting", 4: "Establishing", 5: "Initiating", 6: "Connecting",  7: "Queued", 8:"Address", 9:  "Status", 10: "Offline",11: "Closed",12: "Can't Connect", 13: "Aborted",14: "Not Shared"}
		self.Main = gtk.VBox(False, 5)
		self.Main.set_border_width(3)
		self.Main.show()
		self.hbox1 = gtk.HBox(False, spacing=5)
		self.hbox1.set_border_width(3)
		self.hbox1.show()
		self.Main.pack_start(self.hbox1, False, False)
		
		label1 = gtk.Label(("Downloads"))
		label1.set_padding(0, 0)
		label1.show()
		
		self.hbox1.pack_start(label1, False, False)
		
		
		self.ToggleTree = gtk.CheckButton("Group by Users")
		self.ToggleTree.connect("toggled", self.OnToggleTree)
		self.ToggleTree.show()
		#self.frame.CreateIconButton(gtk.STOCK_INDENT, "stock", self.OnToggleTree, "Group by Users")
		self.hbox1.pack_end(self.ToggleTree, False, False)
		
		
		
		
		
		scrolledwindow1 = gtk.ScrolledWindow()
		scrolledwindow1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		scrolledwindow1.show()
		scrolledwindow1.set_shadow_type(gtk.SHADOW_IN)
		
		self.store = gtk.TreeStore(str, str, str, str, str, str, str, int, int, int )
		
		self.treeview = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		self.create_transfer_columns("downloads")
		self.treeview.set_headers_visible(True)
		
		self.popup_menu = popup = PopupMenu(self.frame, "downloads")
		popup.setup(
			("#" + _("_Retry Transfer(s)"), self.OnRetryDownTransfers, gtk.STOCK_REDO),
			("#" + _("_Abort Transfer(s)"), self.OnAbortDownTransfers, gtk.STOCK_CANCEL),
			("#" + _("_Clear Transfer(s)"), self.OnClearDownTransfers, gtk.STOCK_CLEAR),
			("", None),
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Browse _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		self.treeview.connect("button_press_event", self.OnPopupMenuDownloads)
		self.treeview.show()
		
		scrolledwindow1.add(self.treeview)
	
		self.Main.pack_start(scrolledwindow1, True, True, 0)
		self.selected_transfers = []
		self.selected_users = []
		self.users = {}
		
		
		self.TreeUsers = self.ToggleTree.get_active()
		
	def OnToggleTree(self, widget):
		self.TreeUsers = self.ToggleTree.get_active()
			
		self.RebuildTransfers()
		
	def RebuildTransfers(self):
		newiters = []
		for iter in self.downloads.values():
			if iter in self.users.values():
				pass
			else:
				newiters.append(iter)
		transfers = []
		for i in newiters:
			user = self.store.get_value(i, 0)
			filename = self.store.get_value(i, 1)
			rate = self.store.get_value(i, 2)
			state = self.store.get_value(i, 3)
			filepos = self.store.get_value(i, 4)
			filesize = self.store.get_value(i, 5)
			path = self.store.get_value(i, 6)
			realRate = self.store.get_value(i, 7)
			realPos = self.store.get_value(i, 8)
			realSize = self.store.get_value(i, 9)
			transfers.append([user, filename, rate, state, filepos, filesize, path, realRate, realPos, realSize])
		self.Clear()
		for transfer in transfers:
			user, filename, rate, state, filepos, filesize, path, realRate, realPos, realSize = transfer
			self.append(user, filename, realRate, state, realPos, realSize, path)
		
	def Clear(self):
		self.users.clear()
		self.selected_transfers = []
		self.selected_users = []
		self.downloads.clear()
		self.store.clear()
		
	def append(self, user, filename=None, rate=None, state=None, filepos=None, filesize=None, path=None, error=None, place=None):
		if state == 14:
			state = error
		elif type(state) in (int, long):
			state = self.states[state]
			
		else:
			if state.isdigit():
				state = self.states[int(state)]
			
		if self.TreeUsers:
			if not self.users.has_key(user):
				self.users[user] = self.store.append(None, [user, "", "", "", "", "", "", 0, 0, 0])
	
		parent = None
		if self.TreeUsers:
			parent = self.users[user]
		iters =  self.store.append(parent, [user, path.split("\\")[-1], self.frame.Humanize(rate), state, self.frame.Humanize(filepos), self.frame.Humanize( filesize),   path, rate, filepos, filesize])
		
		self.downloads[(user, path)] =  iters

		
	def update(self, user, filename=None, rate=None, state=None, filepos=None, filesize=None, path=None, error=None, place=None):
		user_path = (user, path)
		if user_path in self.downloads:
			if state == 14:
				state = error
			else:
				state = self.states[state]
			self.store.set(self.downloads[user_path], 0, user, 1, path.split("\\")[-1], 2,  self.frame.Humanize(rate), 3 ,state, 4, self.frame.Humanize(filepos),  5, self.frame.Humanize(filesize),  6, path)
		else:
			self.append(user, filename, rate, state, filepos, filesize, path)
			
	def SelectedTransfersCallback(self, model, path, iter):
		user = model.get_value(iter, 0)
		file = model.get_value(iter, 6)
		self.selected_transfers.append(iter)
		if user not in self.selected_users:
			self.selected_users.append(user)

				
	def select_transfers(self):
		self.selected_transfers = []
		self.selected_users = []
		self.treeview.get_selection().selected_foreach(self.SelectedTransfersCallback)
		
	def OnRetryDownTransfers(self, widget):
		model = self.store
		self.select_transfers()
		for iter in self.selected_transfers:
			user = model.get_value(iter, 0)
			path = model.get_value(iter, 6)
			if path == "": continue
			self.frame.Networking.DownloadFile(user, path)

		
	
	def OnClearDownTransfers(self, widget):
		model = self.store
		self.select_transfers()
		for iter in self.selected_transfers:
			user = model.get_value(iter, 0)
			path = model.get_value(iter, 6)
			if path == "": continue
			self.frame.Networking.TransferRemove(0, user, path)
			
	def OnAbortDownTransfers(self, widget):
		model = self.store
		self.select_transfers()
		for iter in self.selected_transfers:
			user = model.get_value(iter, 0)
			path = model.get_value(iter, 6)
			if path == "": continue
			self.frame.Networking.TransferAbort(0, user, path)
		
	def remove(self, transfer):
		user_path =  transfer[1], transfer[2]
		if user_path in self.downloads:
			self.store.remove(self.downloads[ user_path ])
			del self.downloads[ user_path ]

			
	
	def OnPopupMenuDownloads(self, widget, event):
		if event.button != 3:
			return
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user = self.store.get_value(self.store.get_iter(path), 0)
		file = self.store.get_value(self.store.get_iter(path), 6)
		if file == "" or path == "":
			return True
		self.popup_menu.set_user(user)
		self.popup_menu.set_path(file)
		
		items = self.popup_menu.get_children()
		items[8].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[9].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[10].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[11].set_active(self.frame.Networking.config["trusted"].has_key(user))
		
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.treeview.emit_stop_by_name("button_press_event")
		return True

	def create_transfer_columns(self, direction):
		try:
			cols = InitialiseColumns(self.treeview,
				[_("Username"), 100, "text"], #0
				[_("Filename"), 250, "text"], #1
				[_("Speed"), 50, "text"], #2
				[_("Status"), 80, "text"], #3
				[_("Pos"), 50, "text"], #4
				[_("Size"), 80, "text"], #5
				[_("Path"), 350, "text"], #6
			)
			cols[0].set_sort_column_id(0)
			cols[1].set_sort_column_id(1)
			cols[2].set_sort_column_id(7)
			cols[3].set_sort_column_id(3)
			cols[4].set_sort_column_id(8)
			cols[5].set_sort_column_id(9)
			cols[6].set_sort_column_id(6)
			self.treeview.set_search_column(1)

			#self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
		except Exception, e:
			print e

	
class Uploads:
	def __init__(self, frame):
		self.frame = frame
		self.uploads = {}
		self.states = {0: "Finished", 1: "Transferring", 2: "Negotiating", 3:"Waiting", 4: "Establishing", 5: "Initiating", 6: "Connecting",  7: "Queued", 8:"Address", 9:  "Status", 10: "Offline",11: "Closed",12: "Can't Connect", 13: "Aborted",14: "Not Shared"}
		
		
		self.Main = gtk.VBox(False, 5)
		self.Main.set_border_width(3)
		self.Main.show()
		self.hbox1 = gtk.HBox(False, spacing=5)
		self.hbox1.set_border_width(3)
		self.hbox1.show()
		self.Main.pack_start(self.hbox1, False, False)
		
		label1 = gtk.Label(("Uploads"))
		label1.set_padding(0, 0)
		label1.show()
		
		self.hbox1.pack_start(label1, False, False)
		
		#self.ToggleTree = self.frame.CreateIconButton(gtk.STOCK_INDENT, "stock", self.OnToggleTree, "Group by Users")
		self.ToggleTree = gtk.CheckButton("Group by Users")
		self.ToggleTree.connect("toggled", self.OnToggleTree)
		self.ToggleTree.show()
		self.hbox1.pack_end(self.ToggleTree, False, False)

	
		scrolledwindow2 = gtk.ScrolledWindow()
		scrolledwindow2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		scrolledwindow2.show()
		scrolledwindow2.set_shadow_type(gtk.SHADOW_IN)
		
		self.store = gtk.TreeStore(str, str, str, str, str, str, str, int, int, int )
		self.treeview = gtk.TreeView(self.store)
		self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		self.create_transfer_columns("uploads")
		self.treeview.set_property("rules-hint", True)
		self.treeview.set_headers_visible(True)
		self.popup_menu = popup = PopupMenu(self.frame, "uploads")
		popup.setup(
			("#" + _("_Abort Transfer"), self.OnAbortUpTransfers, gtk.STOCK_CANCEL),
			("#" + _("_Clear Transfer"), self.OnClearUpTransfers, gtk.STOCK_CLEAR),
			("", None),
			("#" + _("_Retry Transfer"), self.OnRetryUpTransfers, gtk.STOCK_CLEAR),
			("", None),
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Browse _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
					)
		self.treeview.connect("button_press_event", self.OnPopupMenuUploads)
		self.treeview.show()
		scrolledwindow2.add(self.treeview)
	
		self.Main.pack_start(scrolledwindow2, True, True, 0)
		self.selected_transfers = []
		self.selected_users = []
		self.TreeUsers = self.ToggleTree.get_active()
		self.users = {}
		
	def Clear(self):
		self.users.clear()
		self.selected_transfers = []
		self.selected_users = []
		self.uploads.clear()
		self.store.clear()
		
	
		
	def OnToggleTree(self, widget):
		self.TreeUsers = self.ToggleTree.get_active()
			
		self.RebuildTransfers()
			
		self.RebuildTransfers()
		
	def RebuildTransfers(self):
		newiters = []
		for iter in self.uploads.values():
			if iter in self.users.values():
				pass
			else:
				newiters.append(iter)
		transfers = []
		for i in newiters:
			user = self.store.get_value(i, 0)
			filename = self.store.get_value(i, 1)
			rate = self.store.get_value(i, 2)
			state = self.store.get_value(i, 3)
			filepos = self.store.get_value(i, 4)
			filesize = self.store.get_value(i, 5)
			path = self.store.get_value(i, 6)
			realRate = self.store.get_value(i, 7)
			realPos = self.store.get_value(i, 8)
			realSize = self.store.get_value(i, 9)
			transfers.append([user, filename, rate, state, filepos, filesize, path, realRate, realPos, realSize])
		self.Clear()
		for transfer in transfers:
			user, filename, rate, state, filepos, filesize, path, realRate, realPos, realSize = transfer
			self.append(user, filename, realRate, state, realPos, realSize, path)
			
	def SelectedTransfersCallback(self, model, path, iter):
		user = model.get_value(iter, 0)
		file = model.get_value(iter, 6)
		self.selected_transfers.append(iter)
		if user not in self.selected_users:
			self.selected_users.append(user)
			
	def select_transfers(self):
		self.selected_transfers = []
		self.selected_users = []
		self.treeview.get_selection().selected_foreach(self.SelectedTransfersCallback)
	## Retry a Upload
	# @param self Uploads
	# @param username Username
	# @param path File path
	def RetryUpload(self, username, path):
		if username == None or path == None:
			return
		path = path.replace("/", "\\")
		self.frame.Networking.UploadFile(username, path)
		#self.mucous.Help.Log("status", "Uploading: [%s] %s" % (username, path))	
		
	def OnRetryUpTransfers(self, widget):
		model = self.store
		self.select_transfers()
		for iter in self.selected_transfers:
			user = model.get_value(iter, 0)
			path = model.get_value(iter, 6)
			if path == "":
				continue
			self.RetryUpload(user, path)

		
	
	def OnClearUpTransfers(self, widget):
		model = self.store
		self.select_transfers()
		for iter in self.selected_transfers:
			user = model.get_value(iter, 0)
			path = model.get_value(iter, 6)
			if path == "":
				continue
			self.frame.Networking.TransferRemove(1, user, path)
			
	def OnAbortUpTransfers(self, widget):
		model = self.store
		self.select_transfers()
		for iter in self.selected_transfers:
			user = model.get_value(iter, 0)
			path = model.get_value(iter, 6)
			if path == "":
				continue
			self.frame.Networking.TransferAbort(1, user, path)
		
	def append(self, user, filename=None, rate=None, state=None, filepos=None, filesize=None, path=None, error=None, place=None):
		user_path = (user, path)
		if state == 14:
			state = error
		elif type(state) in (int, long):
			state = self.states[state]
			
		else:
			if state.isdigit():
				state = self.states[int(state)]
		if self.TreeUsers:
			if not self.users.has_key(user):
				self.users[user] = self.store.append(None, [user, "", "", "", "", "", "", 0, 0, 0])
		parent = None
		if self.TreeUsers:
			parent = self.users[user]
		iters =  self.store.append(parent, [user, path.split("\\")[-1], self.frame.Humanize(rate), state, self.frame.Humanize(filepos), self.frame.Humanize( filesize),   path, rate, filepos, filesize])
		self.uploads[(user, path)] =  iters

		
	def update(self, user, filename=None, rate=None, state=None, filepos=None, filesize=None, path=None, error=None, place=None):
		user_path = (user, path)
		if user_path in self.uploads:
			self.store.set(self.uploads[user_path], 0, user, 1, path.split("\\")[-1], 2, self.frame.Humanize(rate), 3 ,self.states[state], 4, self.frame.Humanize(filepos),  5, self.frame.Humanize(filesize),  6, path, 7, rate, 8, filepos, 9, filesize)
		else:
			self.append(user, filename, rate, state, filepos, filesize, path, rate, filepos, filesize)
			
	def remove(self, transfer):
		user_path =  transfer[1], transfer[2]
		if user_path in self.uploads:
			self.store.remove( self.uploads[ user_path ] )
			del self.uploads[ user_path ]

			
			
	def OnPopupMenuUploads(self, widget, event):
		if event.button != 3:
			return
		items = self.popup_menu.get_children()
		
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user = self.store.get_value(self.store.get_iter(path), 0)
		file = self.store.get_value(self.store.get_iter(path), 6)
		if file == "" or path == "":
			return True
		self.popup_menu.set_user(user)
		self.popup_menu.set_path(file)
		
		items[9].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[10].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[11].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[12].set_active(self.frame.Networking.config["trusted"].has_key(user))
		
		
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.treeview.emit_stop_by_name("button_press_event")
		return True
	
	def create_transfer_columns(self, direction):
		try:
			cols = InitialiseColumns(self.treeview,
				[_("Username"), 100, "text"], #0
				[_("Filename"), 250, "text"], #1
				[_("Speed"), 50, "text"], #2
				[_("Status"), 80, "text"], #3
				[_("Pos"), 50, "text"], #4
				[_("Size"), 80, "text"], #5
				[_("Path"), 350, "text"], #6
			)
			
			self.treeview.set_search_column(1)
			cols[0].set_sort_column_id(0)
			cols[1].set_sort_column_id(1)
			cols[2].set_sort_column_id(7)
			cols[3].set_sort_column_id(3)
			cols[4].set_sort_column_id(8)
			cols[5].set_sort_column_id(9)
			cols[6].set_sort_column_id(6)
			#self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
		except Exception, e:
			print e

class ListsOfUsers(IconNotebook):
	def __init__(self, frame):
		self.frame = frame
		IconNotebook.__init__(self, frame.images)
		
		self.set_border_width(4)
		self.set_tab_pos(gtk.POS_TOP)
		self.set_scrollable(True)
		self.show()

		self.buddies= ListBuddies(self.frame)
		self.append_page(self.buddies.Main, _("Buddies"))
		self.trusted = ListTrusted(self.frame)
		self.append_page(self.trusted.Main, _("Trusted"))
		self.banned = ListBanned(self.frame)
		self.append_page(self.banned.Main, _("Banned"))
		self.ignored = ListIgnored(self.frame)
		self.append_page(self.ignored.Main, _("Ignored"))
		

		
	def updateStats(self, user, stats):
		for w in [ self.buddies, self.trusted, self.banned, self.ignored ]:
			gobject.idle_add(w.updateStats, user, stats)
				
	def updateStatus(self, user, status):
		for w in [ self.buddies, self.trusted, self.banned, self.ignored ]:
			gobject.idle_add(w.updateStatus, user, status)
			
	def updateListIcon(self, user):
		for w in [ self.buddies, self.trusted, self.banned, self.ignored ]:
			gobject.idle_add(w.updateListIcon, user)
class ListBanned:
	def __init__(self, frame):
		# Text input box
		self.frame = frame
		self.entry = entry = gtk.Entry()
		self.users = {}
		entry.set_text("")
		entry.grab_focus()
		entry.show()
		entry.connect("activate", self.EnterBanned, entry)
		
		label = gtk.Label(_("Add User:"))
		label.show()
		
		
		addhbox = gtk.HBox(spacing=3)
		addhbox.set_border_width(3)
		addhbox.pack_start(label, False, False, 0)
		addhbox.pack_end(entry, True, True,  0)
		addhbox.show()
		
		
		self.store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, str, int )
		
		self.treeview = UserList = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		cols = InitialiseColumns(self.treeview,
				[_("Status"), -1, "pixbuf"], #0
				[_("Username"), 100, "text"], #1
				[_("Files"), 50, "text"], #2
				[_("Speed"), 50, "text"], #3
				[_("Comments"), 100, "text"], #4
			)
		cols[0].set_sort_column_id(5)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		cols[4].set_sort_column_id(4)
		#self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
		
		self.popup_menu = popup = PopupMenu(self.frame, "userlists")
		popup.setup(
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Browse _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		UserList.connect("button_press_event", self.OnPopupMenuBanned)
		UserList.show()
		
		# Scrollwindow containing Users-in-room Listbox
		widget = gtk.ScrolledWindow()
		widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		widget.add(UserList)
		widget.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		
		widget.show()
		
		# Containing box with scrolled window and text input box
		self.Main= gtk.VBox(spacing=3)
		self.Main.set_border_width(3)
		self.Main.pack_start(widget, True, True, 0)
		self.Main.pack_end(addhbox, False, False, 0)
		self.Main.show()

		# Naming the tab
		self.label = gtk.Label(_("Banned") )
		self.label.show()
		
	def OnPopupMenuBanned(self, widget, event):
		if event.button != 3:
			return
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user =  self.store.get_value(self.store.get_iter(path), 1)
		self.popup_menu.set_user(user)
		items = self.popup_menu.get_children()
		items[5].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[6].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[7].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[8].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.treeview.emit_stop_by_name("button_press_event")
		return True
	
	def EnterBanned(self, widget, whatever):
		user = self.entry.get_text()
		self.frame.Networking.mod_config("ban", user)
		self.entry.set_text("")
		if user not in self.user_stats:
			self.frame.Networking.PeerExists(user)
				
	def updateStatus(self, user, status):
                if user not in self.users.keys():
                    return
                if status == self.store.get_value(self.users[user], 5):
                  return
                img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateListIcon(self, user):
		if user not in self.users.keys():
			return
		status = self.store.get_value(self.users[user], 5)
		img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateStats(self, user, stats):
                if user not in self.users.keys():
                    return
		status, speed, downloads, files, dirs, exists = stats 
		self.store.set(self.users[user], 1, user, 2, Humanize(files), 3, Humanize(speed))
		
	def update(self, user, comments):
		if user not in self.users:
			return
		self.store.set(self.users[user], 1, user,  4, comments )
		
	def append(self, user, comments):
		if user in self.users:
			return
		if user in self.frame.user_stats:
			status, speed, downloads, files, dirs, exists = self.frame.user_stats[user]
		else:
			status = speed = downloads = files = dirs = 0
		self.users[user] = self.store.append([ self.frame.GetStatusImage(user, status), user,  Humanize(files), Humanize(speed), comments, status ])

	def remove(self, user):
		self.store.remove(self.users[user])
		del self.users[user]
	def clear(self, user):
		self.store.clear()
	
class ListBuddies:
	def __init__(self, frame):
		# Text input box
		self.frame = frame
		self.entry = entry = gtk.Entry()
		self.users = {}
		entry.set_text("")
		entry.grab_focus()
		entry.show()
		entry.connect("activate", self.EnterBuddy, entry)
		
		label = gtk.Label(_("Add User:"))
		label.show()
		
		
		addhbox = gtk.HBox(spacing=3)
		addhbox.set_border_width(3)
		addhbox.pack_start(label, False, False, 0)
		addhbox.pack_end(entry, True, True,  0)
		addhbox.show()
		
		
		self.store = gtk.ListStore(gtk.gdk.Pixbuf, str,str,str, str, int )
		
		self.treeview = UserList = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		cols = InitialiseColumns(self.treeview,
				[_("Status"), -1, "pixbuf"], #0
				[_("Username"), 100, "text"], #1
				[_("Files"), 50, "text"], #2
				[_("Speed"), 50, "text"], #3
				[_("Comments"), 100, "text"], #4
			)
		cols[0].set_sort_column_id(5)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		cols[4].set_sort_column_id(4)

		
		#self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
		
		self.popup_menu = popup = PopupMenu(self.frame, "userlists")
		popup.setup(
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Browse _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		UserList.connect("button_press_event", self.OnPopupMenuBuddies)
		UserList.show()
		
		# Scrollwindow containing Users-in-room Listbox
		widget = gtk.ScrolledWindow()
		widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		widget.add(UserList)
		widget.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		
		widget.show()
		
		# Containing box with scrolled window and text input box
		self.Main= gtk.VBox(spacing=3)
		self.Main.set_border_width(3)
		self.Main.pack_start(widget, True, True, 0)
		self.Main.pack_end(addhbox, False, False, 0)
		self.Main.show()
		
		#vseparator = gtk.VSeparator()
		#vseparator.show()
		
		# Naming the tab
		self.label = gtk.Label("Buddies" ) 
		self.label.show()
		
	def OnPopupMenuBuddies(self, widget, event):
		if event.button != 3:
			return
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user =  self.store.get_value(self.store.get_iter(path), 1)
		self.popup_menu.set_user(user)
		items = self.popup_menu.get_children()
		items[5].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[6].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[7].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[8].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.treeview.emit_stop_by_name("button_press_event")
		return True
	
	
	def EnterBuddy(self, widget, whatever):
		user = self.entry.get_text()
		self.frame.Networking.mod_config("buddy", user)
		self.entry.set_text("")
	
	def updateStatus(self, user, status):
                if user not in self.users.keys():
                    return
		if status == self.store.get_value(self.users[user], 5):
                  return
                img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateListIcon(self, user):
		if user not in self.users.keys():
			return
		status = self.store.get_value(self.users[user], 5)
		img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateStats(self, user, stats):
                if user not in self.users.keys():
                    return
		status, speed, downloads, files, dirs, exists = stats 
		self.store.set(self.users[user], 1, user, 2, Humanize(files), 3, Humanize(speed))
		
	def update(self, user, comments):
		if user not in self.users:
			return
		self.store.set(self.users[user], 1, user,  4, comments )
		
	def append(self, user, comments):
		if user in self.users:
			return
		if user in self.frame.user_stats:
			status, speed, downloads, files, dirs, exists = self.frame.user_stats[user]
		else:
			status = speed = downloads = files = dirs = 0

		self.users[user] = self.store.append([ self.frame.GetStatusImage(user, status), user,  Humanize(files), Humanize(speed), comments, status ])
		
	def remove(self, user):
		self.store.remove(self.users[user])
		del self.users[user]
		
	def clear(self, user):
		self.store.clear()
		
class ListTrusted:
	def __init__(self, frame):
		# Text input box
		self.users = {}
		self.frame = frame
		self.entry = entry = gtk.Entry()
		entry.set_text("")
		entry.grab_focus()
		entry.show()
		entry.connect("activate", self.EnterTrusted, entry)
		
		label = gtk.Label(_("Add User:"))
		label.show()
		
		
		addhbox = gtk.HBox(spacing=3)
		addhbox.set_border_width(3)
		addhbox.pack_start(label, False, False, 0)
		addhbox.pack_end(entry, True, True,  0)
		addhbox.show()
		
		
		self.store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, str, int )
		
		self.treeview = UserList = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		cols = InitialiseColumns(self.treeview,
				[_("Status"), -1, "pixbuf"], #0
				[_("Username"), 100, "text"], #1
				[_("Files"), 50, "text"], #2
				[_("Speed"), 50, "text"], #3
				[_("Comments"), 100, "text"], #4
			)
		cols[0].set_sort_column_id(5)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		cols[4].set_sort_column_id(4)

		
		#self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
		
		self.popup_menu = popup = PopupMenu(self.frame, "userlists")
		popup.setup(
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Browse _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		UserList.connect("button_press_event", self.OnPopupMenuTrusted)
		UserList.show()
		
		# Scrollwindow containing Users-in-room Listbox
		widget = gtk.ScrolledWindow()
		widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		widget.add(UserList)
		widget.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		
		widget.show()
		
		# Containing box with scrolled window and text input box
		self.Main= gtk.VBox(spacing=3)
		self.Main.set_border_width(3)
		self.Main.pack_start(widget, True, True, 0)
		self.Main.pack_end(addhbox, False, False, 0)
		self.Main.show()
		
		#vseparator = gtk.VSeparator()
		#vseparator.show()
		
		# Naming the tab
		self.label = gtk.Label(_("Trusted") )
		self.label.show()
		
	def OnPopupMenuTrusted(self, widget, event):
		if event.button != 3:
			return
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user =  self.store.get_value(self.store.get_iter(path), 1)
		self.popup_menu.set_user(user)
		items = self.popup_menu.get_children()
		items[5].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[6].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[7].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[8].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.treeview.emit_stop_by_name("button_press_event")
		return True
	
	
	def EnterTrusted(self, widget, whatever):
		user = self.entry.get_text()
		self.frame.Networking.mod_config("trust", user)
		self.entry.set_text("")
	
	def updateStatus(self, user, status):
                if user not in self.users.keys():
                    return
		if status == self.store.get_value(self.users[user], 5):
                  return
                img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateListIcon(self, user):
		if user not in self.users.keys():
			return
		status = self.store.get_value(self.users[user], 5)
		img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateStats(self, user, stats):
                if user not in self.users.keys():
                    return
		status, speed, downloads, files, dirs, exists = stats 
		self.store.set(self.users[user], 1, user, 2, Humanize(files), 3, Humanize(speed))
		
	def update(self, user, comments):
		if user not in self.users:
			return
		self.store.set(self.users[user], 1, user,  4, comments )
		
	def append(self, user, comments):
		if user in self.users:
			return
		if user in self.frame.user_stats:
			status, speed, downloads, files, dirs, exists = self.frame.user_stats[user]
		else:
			status = speed = downloads = files = dirs = 0

		self.users[user] = self.store.append([ self.frame.GetStatusImage(user, status), user,  Humanize(files), Humanize(speed), comments, status ])
		
	def remove(self, user):
		self.store.remove(self.users[user])
		del self.users[user]
		
	def clear(self, user):
		self.store.clear()
		
class ListIgnored:
	def __init__(self, frame):
		self.users = {}
		self.frame = frame
		self.entry = entry = gtk.Entry()
		entry.set_text("")
		entry.grab_focus()
		entry.show()
		entry.connect("activate", self.EnterIgnored, entry)
		
		label = gtk.Label(_("Add User:"))
		label.show()
		
		
		addhbox = gtk.HBox(spacing=3)
		addhbox.set_border_width(3)
		addhbox.pack_start(label, False, False, 0)
		addhbox.pack_end(entry, True, True,  0)
		addhbox.show()
		
		
		self.store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, str, int )
		
		self.treeview = UserList = gtk.TreeView(self.store)
		self.treeview.set_property("rules-hint", True)
		cols = InitialiseColumns(self.treeview,
				[_("Status"), -1, "pixbuf"], #0
				[_("Username"), 100, "text"], #1
				[_("Files"), 50, "text"], #2
				[_("Speed"), 50, "text"], #3
				[_("Comments"), 100, "text"], #4
			)
		cols[0].set_sort_column_id(5)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		cols[4].set_sort_column_id(4)

		
		#self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
		
		self.popup_menu = popup = PopupMenu(self.frame, "userlists")
		popup.setup(
			("#" + _("_Private Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("_User Info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("IP A_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Browse _Shares"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		UserList.connect("button_press_event", self.OnPopupMenuIgnored)
		UserList.show()
		
		# Scrollwindow containing Users-in-room Listbox
		widget = gtk.ScrolledWindow()
		widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		widget.add(UserList)
		widget.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		
		widget.show()
		
		# Containing box with scrolled window and text input box
		self.Main= gtk.VBox(spacing=3)
		self.Main.set_border_width(3)
		self.Main.pack_start(widget, True, True, 0)
		self.Main.pack_end(addhbox, False, False, 0)
		self.Main.show()
		
		#vseparator = gtk.VSeparator()
		#vseparator.show()
		
		# Naming the tab
		self.label = gtk.Label(_("Ignored") )
		self.label.show()

	def OnPopupMenuIgnored(self, widget, event):
		if event.button != 3:
			return
		d = self.treeview.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user =  self.store.get_value(self.store.get_iter(path), 1)
		self.popup_menu.set_user(user)
		items = self.popup_menu.get_children()
		items[5].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[6].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[7].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[8].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.popup_menu.popup(None, None, None, event.button, event.time)
		self.treeview.emit_stop_by_name("button_press_event")
		return True
	
	
	def EnterIgnored(self, widget, whatever):
		user = self.entry.get_text()
		self.frame.Networking.mod_config("ignore", user)
		self.entry.set_text("")
	
	def updateStatus(self, user, status):
                if user not in self.users.keys():
                    return
		if status == self.store.get_value(self.users[user], 5):
                  return
                img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateListIcon(self, user):
		if user not in self.users.keys():
			return
		status = self.store.get_value(self.users[user], 5)
		img = self.frame.GetStatusImage(user, status)
		self.store.set(self.users[user], 0, img, 5, status)
		
	def updateStats(self, user, stats):
                if user not in self.users.keys():
                    return
		status, speed, downloads, files, dirs, exists = stats 
		self.store.set(self.users[user], 1, user, 2, Humanize(files), 3, Humanize(speed))
		
	def update(self, user, comments):
		if user not in self.users:
			return
		self.store.set(self.users[user], 1, user,  4, comments )
		
	def append(self, user, comments):
		if user in self.users:
			return
		if user in self.frame.user_stats:
			status, speed, downloads, files, dirs, exists = self.frame.user_stats[user]
		else:
			status = speed = downloads = files = dirs = 0

		self.users[user] = self.store.append([ self.frame.GetStatusImage(user, status), user,  Humanize(files), Humanize(speed), comments, status ])
			
	def remove(self, user):
		self.store.remove(self.users[user])
		del self.users[user]
		
	def clear(self, user):
		self.store.clear()
		
class Recommendations:
	def __init__(self, frame):
		self.frame = frame
		self.users = {}
		self.recommendations = {}
		self.liked = {}
		self.hated = {}
		
		
		self.vbox1 = gtk.VBox(homogeneous=False, spacing=0)
		self.vbox1.show()
		
		self.hbox1 = gtk.HBox(homogeneous=False, spacing=5)
		self.hbox1.show()
		self.hbox1.set_spacing(5)
		self.hbox1.set_border_width(5)
		# Global Recommendations Button
		self.GlobalRecommendationsButton = gtk.Button()
		self.GlobalRecommendationsButton.show()
		
		self.hbox2 = gtk.HBox(homogeneous=False, spacing=3)
		self.hbox2.show()
		
		self.image1 = gtk.Image()
		self.image1.set_from_stock(gtk.STOCK_REFRESH, 4)
		self.image1.show()
		self.hbox2.pack_start(self.image1)
		
		self.label1 = gtk.Label(_("Global Recommendations"))
		self.label1.show()
		self.hbox2.pack_start(self.label1)
		
		self.GlobalRecommendationsButton.add(self.hbox2)
		# Recommendations Button
		self.RecommendationsButton = gtk.Button()
		self.RecommendationsButton.show()
		
		self.hbox4 = gtk.HBox(homogeneous=False, spacing=3)
		self.hbox4.show()
		
		self.image3 = gtk.Image()
		self.image3.set_from_stock(gtk.STOCK_REFRESH, 4)
		self.image3.show()
		self.hbox4.pack_start(self.image3)
		
		self.label3 = gtk.Label(_("Recommendations"))
		self.label3.show()
		self.hbox4.pack_start(self.label3)
		
		self.RecommendationsButton.add(self.hbox4)
		# Similar Users Button
		self.SimilarUsersButton = gtk.Button()
		self.SimilarUsersButton.show()
		
		self.hbox3 = gtk.HBox(homogeneous=False, spacing=3)
		self.hbox3.show()
		
		self.image2 = gtk.Image()
		self.image2.set_from_stock(gtk.STOCK_REFRESH, 4)
		self.image2.show()
		self.hbox3.pack_start(self.image2)
		
		self.label2 = gtk.Label(_("Similar Users"))
		self.label2.show()
		self.hbox3.pack_start(self.label2)
		
		self.SimilarUsersButton.add(self.hbox3)
		
		# Pack
		self.SimilarUsersButton.connect("clicked", self.GetSimilarUsers)
		self.RecommendationsButton.connect("clicked", self.GetRecommendations)
		self.GlobalRecommendationsButton.connect("clicked", self.GetGlobalRecommendations)
		
		self.hbox1.pack_end(self.SimilarUsersButton, False, False, 0)
		self.hbox1.pack_end(self.RecommendationsButton, False, False, 0)
		self.hbox1.pack_end(self.GlobalRecommendationsButton, False, False, 0)
		
		self.vbox1.pack_start(self.hbox1, False, False, 0)
		
		# Interests, Recommendations, and Similar Users Lists
		self.hpaned1 = gtk.HPaned()
		self.hpaned1.show()
		self.hpaned1.set_border_width(5)
		
		self.vbox2 = gtk.VBox(homogeneous=False, spacing=5)
		self.vbox2.show()
		# Liked Items
		self.LikesStore = gtk.ListStore( str )
		self.LikesTreeView = gtk.TreeView(self.LikesStore)
		cols0 = InitialiseColumns(self.LikesTreeView, 
			[_("I Like..."), 0, "text"], #1
		)
		cols0[0].set_sort_column_id(0)
		self.likes_popup_menu = popup = PopupMenu(self.frame, "likes")
		popup.setup(
			("#" + _("_Remove this item"), self.OnRemoveLikedInterest, gtk.STOCK_CANCEL),
			("#" + _("Re_commendations for this item"), self.OnInterestRecommendations, gtk.STOCK_INDEX),
		)
		self.LikesTreeView.connect("button_press_event", self.OnPopupLikes)
		self.LikesSW = gtk.ScrolledWindow()
		self.LikesSW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		
		self.LikesSW.add_with_viewport(self.LikesTreeView)
		self.LikesSW.show()
		self.vbox2.pack_start(self.LikesSW)
		
		self.AddLikedButton = self.frame.CreateIconButton(gtk.STOCK_ADD, "stock", self.OnAddLikedInterest, "Add")
	
		self.vbox2.pack_start(self.AddLikedButton, False, False)
		# Hated Items
		self.HatesStore = gtk.ListStore( str )
	
		self.HatesTreeView = gtk.TreeView(self.HatesStore)
		cols1 = InitialiseColumns(self.HatesTreeView, 
			[_("I Hate..."), 0, "text"], #1
		)
		cols1[0].set_sort_column_id(0)
		self.hated_popup_menu = popup = PopupMenu(self.frame, "hated")
		popup.setup(("#" + _("Remove this item"), self.OnRemoveHatedInterest, gtk.STOCK_CANCEL))
		self.HatesTreeView.connect("button_press_event", self.OnPopupHated)
		
		self.HatesSW = gtk.ScrolledWindow()
		self.HatesSW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.HatesSW.add_with_viewport(self.HatesTreeView)
		self.HatesSW.show()
		
		self.vbox2.pack_start(self.HatesSW)
		
		self.AddHatedButton = self.frame.CreateIconButton(gtk.STOCK_ADD, "stock", self.OnAddHatedInterest, "Add")

		self.vbox2.pack_start(self.AddHatedButton, False, False)
		
		self.hpaned1.pack1(self.vbox2, False, False)
		
		self.hpaned2 = gtk.HPaned()
		self.hpaned2.show()
		# Recommendations
		self.RecommendationsStore = gtk.ListStore( str, int )
		self.RecommendationsTreeView = gtk.TreeView(self.RecommendationsStore)
		
		cols2 = InitialiseColumns(self.RecommendationsTreeView, 
			[_("Recommendations"), 150, "text"], #1
			[_("Rating"), 0, "text"], #2
		)

		cols2[0].set_sort_column_id(0)
		cols2[1].set_sort_column_id(1)
		
		self.RecommendationsSW = gtk.ScrolledWindow()
		self.RecommendationsSW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.RecommendationsSW.add_with_viewport(self.RecommendationsTreeView)
		self.RecommendationsSW.show()
		
		
		self.rec_popup_menu = popup = PopupMenu(self.frame, "recommendations")
		popup.setup(
			("$" + _("I _like this"), self.OnAddLikeRecommendation),
			("$" + _("I _don't like this"), self.OnAddHatedRecommendation),
			("#" + _("_Recommendations for this item"), self.OnItemRecommendations, gtk.STOCK_INDEX),
			("", None),
			("#" + _("_Search for this item"), self.OnSearchRecommendations, gtk.STOCK_FIND),
		)
		self.RecommendationsTreeView.connect("button_press_event", self.OnPopupRecommendation)	
		self.hpaned2.pack1(self.RecommendationsSW, False, False)
		# Similar Users
		
		self.SimilarUsersStore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, int )
		self.SimilarUsersTreeView = gtk.TreeView(self.SimilarUsersStore)
		self.SimilarUsersTreeView.set_property("rules-hint", True)
		# Users-in-room Listbox with users and files
		
		cols = InitialiseColumns(self.SimilarUsersTreeView, 
			["", -1, "pixbuf"], #0
			[_("Username"), 100, "text"], #1
			[_("Files"), 0, "text"], #2
			[_("Speed"), 0, "text"], #3
		)
		
		cols[0].set_sort_column_id(4)
		cols[1].set_sort_column_id(1)
		cols[2].set_sort_column_id(2)
		cols[3].set_sort_column_id(3)
		
		self.users_popup_menu = popup = PopupMenu(self.frame, "similar_users")
		popup.setup(
			("#" + _("Private _Message"), popup.OnSendMessage, gtk.STOCK_EDIT),
			("", None),
			("#" + _("Show IP address"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
			("#" + _("Get user info"), popup.OnGetUserInfo, gtk.STOCK_INFO),
			("#" + _("Browse files"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
			("$" + _("_Buddy this user"), popup.OnBuddyUser),
			("$" + _("Ba_n this user"), popup.OnBanUser),
			("$" + _("_Ignore this user"), popup.OnIgnoreUser),
			("$" + _("_Trust this user"), popup.OnTrustUser),
		)
		self.SimilarUsersTreeView.connect("button_press_event", self.OnPopupSimilarUsers)
		
		self.SimilarUsersSW = gtk.ScrolledWindow()
		self.SimilarUsersSW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.SimilarUsersSW.add_with_viewport(self.SimilarUsersTreeView)
		self.SimilarUsersSW.show()
		
		self.hpaned2.pack2(self.SimilarUsersSW, False, False)
		
		self.hpaned1.pack2(self.hpaned2, False, False)
		
		self.vbox1.pack_start(self.hpaned1)
		
		self.Main = self.vbox1

	def OnPopupHated(self, widget, event):
		if event.button != 3:
			return
		items = self.hated_popup_menu.get_children()
		d = self.HatesTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		interest = self.HatesStore.get_value(self.HatesStore.get_iter(path), 0)
		self.hated_popup_menu.set_user(interest)
		self.hated_popup_menu.popup(None, None, None, event.button, event.time)
		self.HatesTreeView.emit_stop_by_name("button_press_event")
		return True
	
	def OnPopupLikes(self, widget, event):
		if event.button != 3:
			return
		items = self.likes_popup_menu.get_children()
		d = self.LikesTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		interest = self.LikesStore.get_value(self.LikesStore.get_iter(path), 0)
		self.likes_popup_menu.set_user(interest)
		self.likes_popup_menu.popup(None, None, None, event.button, event.time)
		self.LikesTreeView.emit_stop_by_name("button_press_event")
		return True
	
	def OnPopupRecommendation(self, widget, event):
		if event.button != 3:
			return
		items = self.rec_popup_menu.get_children()
		d = self.RecommendationsTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		interest = self.RecommendationsStore.get_value(self.RecommendationsStore.get_iter(path), 0)
		self.rec_popup_menu.set_user(interest)
		self.rec_popup_menu.popup(None, None, None, event.button, event.time)
		self.RecommendationsTreeView.emit_stop_by_name("button_press_event")
		return True
	
	
	
	def OnPopupSimilarUsers(self, widget, event):
		if event.button != 3:
			return
		
		d = self.SimilarUsersTreeView.get_path_at_pos(int(event.x), int(event.y))
		if not d:
			return
		path, column, x, y = d
		user = self.SimilarUsersStore.get_value(self.SimilarUsersStore.get_iter(path), 1)
		self.users_popup_menu.set_user(user)
		num = 5
		items = self.users_popup_menu.get_children()
		items[num].set_active(self.frame.Networking.config["buddies"].has_key(user))
		items[num+1].set_active(self.frame.Networking.config["banned"].has_key(user))
		items[num+2].set_active(self.frame.Networking.config["ignored"].has_key(user))
		items[num+3].set_active(self.frame.Networking.config["trusted"].has_key(user))
		self.users_popup_menu.popup(None, None, None, event.button, event.time)
		self.SimilarUsersTreeView.emit_stop_by_name("button_press_event")
		return True
	
	def OnAddLikeRecommendation(self, widget):
		pass
	def OnAddHatedRecommendation(self, widget):
		pass

	def OnItemRecommendations(self, widget):
		pass
	def OnSearchRecommendations(self, widget):
		pass	
	
	def OnAddLikedInterest(self, widget):
		interest = self.frame.PopupEntry(title='Add Liked Interest',
		message='Enter something you like:',
		default_text='')
		self.frame.Networking.AddInterest(interest)

	def OnAddHatedInterest(self, interest):
		interest = self.frame.PopupEntry(title='Add Hated Interest',
		message='Enter something you do not like:',
		default_text='')
		self.frame.Networking.AddHatedInterest(interest)
		
	def OnRemoveLikedInterest(self, widget):
		interest = self.likes_popup_menu.user
		if interest != "" and interest != None and self.frame.Networking.config["interests.like"].has_key(interest):
			
			self.frame.Networking.RemoveInterest(interest)
	
	def OnInterestRecommendations(self, widget):
		interest = self.likes_popup_menu.user
		if interest != "" and interest != None and self.frame.Networking.config["interests.like"].has_key(interest):
			self.frame.Networking.GetItemRecommendations(interest)
			self.frame.Networking.GetItemSimilarUsers(interest)
			
			
	def OnRemoveHatedInterest(self, widget):
		interest = self.hated_popup_menu.user
		if interest != "" and interest != None and self.frame.Networking.config["interests.hate"].has_key(interest):
			self.frame.Networking.RemoveHatedInterest(interest)
	
	def AddedLikedInterest(self, interest):
		if interest in self.liked:
			return
		iter = self.LikesStore.append([interest])
		self.liked[interest] = iter
	def AddedHatedInterest(self, interest):
		if interest in self.hated:
			return
		iter = self.HatesStore.append([interest])
		self.hated[interest] = iter
	def RemovedLikedInterest(self, interest):
		if interest not in self.liked:
			return
		self.LikesStore.remove(self.liked[interest])
		del self.liked[interest]
	def RemovedHatedInterest(self, interest):
		if interest not in self.hated:
			return
		self.HatesStore.remove(self.hated[interest])
		del self.hated[interest]
	def GetGlobalRecommendations(self, widget):
		self.frame.Networking.GetGlobalRecommendations()
	def GetRecommendations(self, widget):
		self.frame.Networking.GetRecommendations()
	def GetSimilarUsers(self, widget):
		self.frame.Networking.GetSimilarUsers()

	def UpdateRecommendations(self, ListOfRecommendations):
		self.RecommendationsStore.clear()
		self.recommendations = {}
		for rec, num in ListOfRecommendations.items():
			#print rec, num
			iter = self.RecommendationsStore.append([rec, num])
			self.recommendations[rec] = iter
			
	def UpdateSimilarUsers(self, ListOfSimilarUsers):
		self.SimilarUsersStore.clear()
		self.users = {}
		if DEBUG: print ListOfSimilarUsers
		for username, status in ListOfSimilarUsers.items():
			if self.frame.user_stats.has_key(username):
				if DEBUG: print username
				status2, speed, downloads, files, dirs, exists = self.frame.user_stats[username]
			else:
				speed = downloads = files = dirs = 0
				self.frame.user_stats[username] = status, speed, downloads, files, dirs, 1 
			img = self.frame.GetStatusImage(username, status)
			hspeed = Humanize(speed)
			hfiles = Humanize(files)
			iter = self.SimilarUsersStore.append([img, username, hfiles, hspeed, status])
			self.users[username] = iter
	
class Murmur( Networking):

	def __init__(self):

		gtk.gdk.threads_init()
		signal.signal(signal.SIGINT, signal.SIG_DFL)
		self.DEBUG = DEBUG
		
		# default config
		self.Config = {"connection":{"interface":'localhost:2240', "passw":None}, \
			"museekd": {"configfile": os.path.expanduser("~/.museekd/config.xml")}, \
			"murmur":{"trayapp": "yes", "tooltips": "no", "autobuddy": "no", "roomlistminsize": 5, \
			"rooms_sort": "size", "roombox": "big", "now-playing": "default", \
			"now-playing-prefix": None, "browse_display_mode": "filesystem", \
			"url reader": "firefox", "url custom prefix": ""}, \
			"colors": { "chatme":"FOREST GREEN", "chatremote":"", "useronline":"BLACK", "useraway":"ORANGE","useroffline":"#aa0000", "chatlocal":"BLUE", \
			"chathilite":"red", "search":"","searchq":"GREY", "chatfont": "" },\
			"logging": { "logcollapsed": "no", "log_dir": "~/.murmur/logs/", "logrooms": 
			"yes", "rooms":[]} \
			}

		## @var config_manager
		# ConfigManager (Class)
		self.config_manager = ConfigManager(self)
		self.config_manager.check_path()
		
		self.username = None
 		self.Config["connection"]["passw"]
		self.pid = pid
		self.timer = None
		self.status = None
		

		self.statusbar = None
		

		
		
		self.statusbarmessage = "Offline"
		
		
		self.chatlog = []
		#self.room_lists = {} # the actual rooms
		self.lists_rooms = None # pygtk ListView index
		self.user_stats = {}
		self.ip_requested = []
		self.TrayApp = TrayApp(self)

		self.CreateMurmurWindow()
		self.MurmurWindow.set_title(_("Murmur") + " " + version)
		
		self.subprocess_fail=0	
		try:
			import subprocess
			self.subprocess = subprocess
		except ImportError:
			self.subprocess_fail=1
			
		self.Networking = Networking(self)
		#self.murmur_config = murmur_config
		self.Settings = Settings(self)
		self.EntryDialog = EntryDialog(self)
		self.ImageDialog = ImageDialog(self)
		self.Logging = Logging(self)
		self.Muscan = Muscan(self)
		
		if self.Config["murmur"]["trayapp"] == "yes":
			self.TrayApp.trayapp("")
		self.quit_w = "No"
		self.Networking.start()

		self.MurmurWindow.show_all()
		utils.USERNAMEHOTSPOTS = 1
		
		
	def disconnect(self, string):
		self.Networking.disconnect("")
		
	def connect_process(self, string):
		
		
		self.MurmurWindow.show_all()
		
		self.Networking.connect_to_museekd("") 

		
	#def run(self):
		
		##self.MurmurWindow.show_all()
		#if self.Config["connection"]["passw"] == None or self.Config["connection"]["passw"] == "None":
			#self.popup( "settings")
		
	
	def AppendToLogWindow(self, message, bug=0):
		AppendLine(self.LogWindow, message, None)
		if self.Config["logging"]["logcollapsed"] == "yes":
			self.update_statusbar(message)
			
	def update_statusbar(self, message):
		try:
			self.statusbarmessage = message
			if self.statusbar != None:
				if self.context_id != None:
					self.statusbar.push(self.context_id, self.statusbarmessage)
		except Exception, e:
			if DEBUG == True: print "update_statusbar", Exception, e
	def PrintTraceBack(self):
		tb = traceback.extract_tb(sys.exc_info()[2])
		for line in tb:
			print line
	def GetStatusImage(self, user, num):
		bud = self.Networking.config["buddies"].has_key(user)
		ban = self.Networking.config["banned"].has_key(user)
		ign = self.Networking.config["ignored"].has_key(user)
		tru = self.Networking.config["trusted"].has_key(user)

		if num == 0:
			image = "offline"
		elif num == 1:
			image = "away"
		elif num == 2:
			image = "online"

		if num in (0, 1, 2):
			if ban:
				image += "_banned"
			elif ign:
				image += "_ignored"
			elif tru:
				image += "_trusted"
			elif bud:
				image += "_buddied"
		if num == 0:
			if self.user_stats.has_key(user):
				if not self.user_stats[user][5]:
					#if not ban and not ign and not tru and not bud:
					image = "noexist"
			else:
				#if not ban and not ign and not tru and not bud:
				image = "noexist"
		return  self.images[image]
	
	def OpenImage(self, widget, title, filters):
		dialog = gtk.FileChooserDialog(title=title, parent=None, action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
		dialog.set_select_multiple(False)
		dialog.set_current_folder_uri("file://"+pwd.getpwuid(os.getuid())[5])
		ff = gtk.FileFilter()
		for ffilter in filters:
			ff.add_pattern(ffilter)
			

		dialog.set_property("filter", ff)
		response = dialog.run()
		
		if response == gtk.RESPONSE_ACCEPT:
			
			res = dialog.get_filenames()
			for files in res:
				file = files
		else:
			file = res = None
		
		dialog.destroy()
		return file
		
	def OnOpenImage(self, widget):
		newimage = self.OpenImage(widget, _("Select an Userinfo Image"), ["*.jpg", "*.jpeg", "*.png","*.bmp", "*.xpm", "*.ico","*.gif"])
		if newimage != None:
			try:
				shutil.copy(newimage, self.Networking.config["userinfo"]["image"] )
				pass

			except Exception, e:
				if self.DEBUG == True: print "Creating image", str(e)
		
	
			
	def byte_format(self, filesize):
		filesize =  int(filesize)
		if filesize >= 1073741824:
			filefrmt = str(filesize/1024/1024/1024) +"GB"
		elif filesize >= 1048576 and filesize <= 1073741824:
			filefrmt = str(filesize/1024/1024) +"MB"
		elif filesize < 1048576 and filesize >= 1024:
			filefrmt = str(filesize/1024) +"KB"
		elif filesize < 1024 and filesize > 0:
			filefrmt = str(filesize) +" B"	
		elif filesize == 0:
			filefrmt = '0'
		return filefrmt
		

			
	def Length2Time(self, length):
		if length != '' and length != None:
			minutes = int(length)/60
			seconds = str( int(length) - (60 * minutes))
			if len(seconds) < 2:
				seconds = '0' + seconds
			length = str(minutes)+":"+str(seconds)
		else:
			length = "0:00"
		return length
		
	

 	def window_quit(self, w=None, event=None):
		self.config_manager.update_config()
 		self.MurmurWindow.hide()
 		self.MurmurWindow.destroy()
		self.MurmurWindow = None
 		#gtk.main_quit()
		
		quit_on_close = True
		if quit_on_close == True:
			
			os._exit(0)
		
	def click(self, button):
		self.MurmurWindow.ret = None
		self.MurmurWindow.quit()

	def quit(self, string):
		os._exit(0)
		
	def userstatus(self, string):
		try:
			if self.status:
				stat = "Away"
			else:
				stat = "Online"
			if self.username != None:
				message="%s is %s" % (self.username, stat)
			else:
				message="You are Offline"
	
			self.AppendToLogWindow(message)
		except Exception,e:
			if DEBUG == True: print "userstatus ERROR", e

	def about(self, string):
		try:
			title=_('About Murmur')
			win = ImageDialog(self, title=title,
			message="<b>Murmur</b> is a PyGTK <b>Museek-Plus</b> client."\
"\nCreator: daelstorm"\
"\n\nMuseek-Plus Website: http://www.museek-plus.source-forge.net/"\
"\nMuseek-Plus Trac: http://www.museek-plus.org/"\

"\nWebpage: http://thegraveyard.org/daelstorm/murmur.php"\
"\nTrac: http://www.museek-plus.org/wiki/murmur"\
, picture = self.images["logo"])
			win.set_title(title)
			win.show()
			gtk.main()
			win.destroy()

			return win.ret
		except Exception,e:
			if DEBUG == True: print "about ERROR", e
			
	def ChatRoomCommands(self, widget):
		helpdict = [
		[00, "", _("Usernames with spaces not supported in two-part commands")],
		[01, "/join <i>room</i>", _("Join a Room")], \
		[02, "/close /c /leave /l /part /p", _("Close tab / Leave Room")],\
		[03, "/pm <i>username</i>", _("Open a Private Chat with a user")], 
		[04, "/msg /m <i>username</i> <i>message</i>", _("Send a user a private message")],\
		[05, "/browse /b <i>username</i>", _("Browse a user")],\
		[06, "/w /whois /info <i>username</i>", _("Get Userinfo")],\
		[07, "/ip <i>username</i>", _("Get a user's IP address")],\
		[8, "\n/add /a /buddy <i>username</i>", _("\nAdd a user your buddy list")], \
		[9, "/unbuddy /un /rem <i>username</i>", _("Remove user from your buddy list")], \
		[10, "/trust <i>username</i>", _("Add a user your trusted list")], \
		[11, "/distrust <i>username</i>", _("Remove user from your trusted list")], \
		[12, "/ban <i>username</i>", _("Add a user your banned list")], \
		[13, "/unban <i>username</i>", _("Remove user from your banned list")], \
		[14, "/ignore <i>username</i>", _("Add a user your ignored list")], \
		[15, "/unignore <i>username</i>", _("Remove user from your ignored list")], \
		#"16\n/tick /t <i>message</i>", _("\nSet ticker"), \
		[17, "/nsa <i>username</i>", _("Get user's Info and Shares")], \
		[18, "/ctcpversion <i>username</i>", _("Request user's Client version (supported by Nicotine-Plus / Museek-Plus)")],\
		
		[19, "\n/search /s <i>query</i>", _("\nSearch for Query")], \
		[20, "/bsearch /bs <i>query</i>", _("Search all Buddies for Query")], \
		[21, "/rsearch /rs <i>query</i>", _("Search all Rooms for Query")], \
		[22, "/usearch /us <i>username</i> <i>query</i>", _("Search a user")], \
		
		[23, "\n/clear /cl", _("Clear Log")], \
		[24, "/quit /q", _("Quit Murmur")] ]
		OpenHelpDialog(self, title="Help", message=_("<b>Chat Commands</b>"), modal= True, helpdict=helpdict, sort=True)
		
	def SharesCommands(self, widget):
		helpdict = [
		[00, "/reload", _("Reload Shares Database from disk (after a update or rescan)")],\
		[01, "\n/updatenormal", _("\nUpdate Normal Shares")], \
		[02, "/updatebuddy", _("Update Buddy Shares")], \
		[03, "/rescan", _("Rescan Normal and Buddy Shares")], \
		[04, "/rescannormal", _("Rescan Normal Shares")], \
		[05, "/rescanbuddy", _("Rescan Buddy Shares")], \
		[06, "/addnormaldir <i>/path</i>", _("Add a Directory to Normal Shares")], \
		[07, "/addbuddydir <i>/path</i>", _("Add a Directory to Buddy Shares")], \
		[8, "/removenormaldir <i>/path</i>", _("Remove a Directory from Normal Shares")], \
		[9, "/removebuddydir <i>/path</i>", _("Remove a Directory from Buddy Shares")], \
		[10, "\n/listshares", _("\nList All Shares")], \
		[11, "/listnormal", _("List Normal Shares")], \
		[12, "/listbuddy", _("List Buddy Shares") ] ]
		OpenHelpDialog(self, title="Help", message=_("<b>Shares Commands</b>"), modal= True, helpdict=helpdict, sort=True)
		
	def PopupEntry(self, title="Input Box", message="", default_text='', modal= True, List=[]):
		try:
			win = EntryDialog(self, message, default_text, modal=modal, droplist=List)
			win.set_title(title)
			win.show()
			gtk.main()
			
			return win.ret
		
		except Exception,e:
			if DEBUG == True: print "PopupEntry ERROR", e

	def PopupEntryPrivate(self, string, buf):
		user = self.PopupEntry(title='Open Private Message',
		message='Enter the user you wish to Send Private Messages to:',
		default_text='', List=self.Networking.config["buddies"].keys())
		if user != None and user != "":
			self.PrivateChats.SendMessage(user)
		
	def PopupEntryJoinRoom(self, string, buf):
		room = self.PopupEntry(title='Join a room',
		message='Enter the room you wish to Join:',
		default_text='', List=self.ChatRooms.rooms.keys())
		if room != None and room != "":
			self.JoinARoom(room)

	def PopupEntryLeaveRoom(self, string, buf):
		room = self.PopupEntry(title='Leave a room',
		message='Enter the room you wish to Leave:',
		default_text='', List=self.ChatRooms.rooms.keys())
		if room != None and room != "":
			self.RoomLeave(room)
			
	def settings(self, modal=True):
		try:

			win = self.Settings
			win.set_title("Murmur Settings")

			win.read_config()
			win.show()

			return 1
		
		except Exception,e:
			if DEBUG == True: print "settings ERROR", e
	
	def SettingsWindow(self, string):
		try:
			result = self.settings()
			if result is None:
				pass
			else:
				if DEBUG == True:
					print "popup: "+str(result)
		except Exception,e:
			if DEBUG == True: print "popup ERROR", e

		
	def LookupUserShares(self, string):
		try:
			user = self.PopupEntry(title='Browse User',
			message='Enter the username of the user who\'s Shares you wish to Browse:',
			default_text='', List=self.Networking.config["buddies"].keys())
			if user is not None:
				self.GetShares(user)
		except Exception,e:
			if DEBUG == True: print "LookupUserShares ERROR", e
	
	def LookupUserInfo(self, string):
		try:
			user = self.PopupEntry(title='Lookup Userinfo',
			message='Enter the username of the user who\'s UserInfo you wish to see:',
			default_text='', List=self.Networking.config["buddies"].keys())
			if user is not None:
				self.GetUserInfo(user)

		except Exception,e:
			if DEBUG == True: print "LookupUserInfo ERROR", e
			
	def LookupIP(self, string):
		try:
			user = self.PopupEntry(title='Lookup IP',
			message='Enter the username of the user who\'s IP you wish to know:',
			default_text='', List=self.Networking.config["buddies"].keys())
			if user is not None:
				self.GetIPAddress(user)

		except Exception,e:
			if DEBUG == True: print "LookupIP ERROR", e
				
	def away_toggle(self, string):
		try:
			if self.username != None:
				if self.status == 0:
					self.Networking.SetStatus(1)
				elif self.status == 1:
					self.Networking.SetStatus(0)
			else:
				self.AppendToLogWindow(_("You are disconnected from Museek"))

		except Exception,e:
			if DEBUG == True: print "away_toggle ERROR", e
			
			
	def CheckNick(self):
		try:

			if self.username == None:
				if DEBUG == True:
					#print "Joined room: %s" % room
					print "Connection is taking a while to start, maybe you are trying to connect to a FTP daemon?"
					print "Killing connection.."
					print "Try using /interface to connect to a different port."
				driver.Driver.close(self)
		except Exception,e:
			if DEBUG == True: print "CheckNick ERROR", e	

			
	def ToggleLogWindow(self, widget, buf):
		active = widget.get_active()

		if active:
			if self.LogScrolledWindow in self.vpaned1.get_children():
				self.vpaned1.remove(self.LogScrolledWindow)
				self.Config["logging"]["logcollapsed"] = "yes"

		else:
			if not self.LogScrolledWindow in self.vpaned1.get_children():
				self.vpaned1.pack2(self.LogScrolledWindow, False, True)
				ScrollBottom(self.LogScrolledWindow)
				self.Config["logging"]["logcollapsed"] = "no"	
			
	def CreateIconButton(self, icon, icontype, callback, label=None):
		button = gtk.Button()
		button.connect_object("clicked", callback, "")
		button.show()
		
		Alignment = gtk.Alignment(0.0, 0.5, 0, 0)
		Alignment.show()
	
		Hbox = gtk.HBox(False, 2)
		Hbox.show()
		Hbox.set_spacing(2)
	
		image = gtk.Image()
		image.set_padding(0, 0)
		if icontype == "stock":
			image.set_from_stock(icon, 4)
		else:
			image = gtk.Image()
			image.set_from_pixbuf(icon)
		image.show()
		Hbox.pack_start(image, False, False, 0)
		Alignment.add(Hbox)
		if label:
			Label = gtk.Label(label)
			Label.set_padding(0, 0)
			Label.show()
			Hbox.pack_start(Label, False, False, 0)
		button.add(Alignment)
		return button
		
		
	def CreateMurmurWindow(self):

		self.accel_group = gtk.AccelGroup()

		self.MurmurWindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.MurmurWindow.set_default_size(700, 500)
		self.MurmurWindow.set_position(gtk.WIN_POS_CENTER)
		self.MurmurWindow.add_accel_group(self.accel_group)
		self.MurmurWindow.show()
		
		self.MurmurWindow.connect("destroy", self.window_quit)
		self.MurmurWindow.connect("delete_event", self.window_quit)
		
		self.clip_data = ""
		self.current_tab = 0
		self.MurmurWindow.connect("selection_get", self.OnSelectionGet)
		self.MurmurWindow.connect("focus_in_event", self.OnFocusIn)
		self.MurmurWindow.connect("focus_out_event", self.OnFocusOut)
		#self.f = None
		
		self.imagedirectory = "images"
		self.images = {}
		
		for i in "away",  "online",  "offline", "noexist", "logo", "close", "green", "yellow", "red", "icon", "away_trusted", "away_banned", "away_buddied", "away_ignored", "online_trusted", "online_banned", "online_ignored", "online_buddied", "offline_trusted", "offline_banned", "offline_ignored", "offline_buddied", "hilite", "empty":
			loader = gtk.gdk.PixbufLoader("png")
			data = getattr(imagedata, i)
			loader.write(data, len(data))
			loader.close()
			self.images[i] = loader.get_pixbuf()
			del loader, data
		gc.collect()
		self.MurmurWindow.set_icon(self.images["icon"])

		#self.transfers= {"uploads": {}, "downloads": {} }

		self.roomtab = None
		
		#self.close_image = os.path.join(self.imagedirectory, "x.png")
		#self.close_image = self.images["close"]
		vbox_murmurwindow = gtk.VBox()
		vbox_murmurwindow.set_spacing(2)
	
		########################
		# Menu bar
		########################
		self.MainMenu = self.CreateMainMenu()
		########################
		vbox_murmurwindow.pack_start(self.MainMenu, False, False, 0)
		self.vpaned1 = gtk.VPaned()
		self.vpaned1.set_border_width(4)
		self.notebook_outside = gtk.Notebook()
		self.notebook_outside.set_tab_pos(gtk.POS_TOP)
		self.notebook_outside.set_scrollable(False)
		
		self.LogWindow = gtk.TextView()
		self.LogWindow.set_wrap_mode(gtk.WRAP_WORD)
		self.LogWindow.set_cursor_visible(False)
		self.LogWindow.set_editable(False)
		self.LogWindow.show()
		
		self.LogScrolledWindow = gtk.ScrolledWindow()
		self.LogScrolledWindow.set_border_width(1)
		self.LogScrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.LogScrolledWindow.set_shadow_type(gtk.SHADOW_IN)
		self.LogScrolledWindow.add_with_viewport(self.LogWindow)
		self.LogScrolledWindow.show()
		# Vertically arrange tabs and log window
		self.vpaned1.pack1(self.notebook_outside, True, True)

		if self.Config["logging"]["logcollapsed"] == "no":
			self.vpaned1.pack2(self.LogScrolledWindow)
		else:
			self.ItemLogWindow.set_active(1)
        	self.vpaned1.show()
		vbox_murmurwindow.pack_start(self.vpaned1, True, True, 0)				
		self.statusbar = gtk.Statusbar()
		self.context_id = self.statusbar.get_context_id("")
		self.statusbar.push(self.context_id, self.statusbarmessage)
		self.statusbar.show()
		vbox_murmurwindow.pack_end(self.statusbar, False, False, 0)
		
 		#self.MurmurWindow.action_area.hide()

		vbox_murmurwindow.show()
		#self.MurmurWindow.set_default(vbox_murmurwindow)
		#if create:
            	self.MurmurWindow.add(vbox_murmurwindow)
		
				
		self.notebook_roomlist = gtk.Frame()
		self.notebook_roomlist.show()	

		# Chat Room Construction
		
		
		self.ChatRooms = ChatRooms(self)
		self.ChatRoomsVbox = gtk.VBox()
		self.ChatRoomsVbox.set_border_width(5)
		self.ChatRoomsVbox.pack_start(self.ChatRooms)
		self.ChatRoomsVbox.show()
		
		# Private Chat Construction
		self.privatevbox = gtk.VBox(False, 0)
		self.privatevbox.show()
		self.privatevbox.set_spacing(0)
	
		self.PrivateChats = PrivateChats(self)
		
	
		self.hbox20 = gtk.HBox(False, 5)
		self.hbox20.show()
		self.hbox20.set_spacing(5)
		self.hbox20.set_border_width(5)
		
		# Entry
		self.PrivateChatEntry = gtk.Entry()
		self.PrivateChatEntry.set_text("")
		self.PrivateChatEntry.set_editable(True)
		self.PrivateChatEntry.show()
		self.PrivateChatEntry.set_visibility(True)
		self.hbox20.pack_start(self.PrivateChatEntry, False, True, 0)
		self.PrivateChatEntry.connect("activate", self.OnGetPrivateChat)
		
		# Button
		self.sPrivateChatButton = self.CreateIconButton(gtk.STOCK_JUMP_TO, "stock", self.OnGetPrivateChat, "Start Message")
		
		
		
		self.hbox20.pack_start(self.sPrivateChatButton, False, False, 0)
		# Private Alignment
		self.privatevbox.pack_start(self.hbox20, False, True, 0)
		self.privatevbox.pack_start(self.PrivateChats, True, True, 0)
		# Transfers Construction
		self.notebook_transfers = gtk.Frame()
		self.notebook_transfers.show()

		vpaned1 = gtk.VPaned()
		self.downloads = Downloads(self)
		vpaned1.pack1(self.downloads.Main, False, True)
		self.uploads = Uploads(self)
		vpaned1.pack2(self.uploads.Main, False, True)
		vpaned1.show()
		#vpaned1.pack2(self.Main, False, True)

		self.notebook_transfers.add(vpaned1)

		
		
		# Searches Construction
		self.Searches = Searches(self)
		self.SearchVbox = gtk.VBox(False, 0)
		self.SearchVbox.show()
		self.SearchVbox.set_spacing(0)
	
		hbox1 = gtk.HBox(False, 5)
		hbox1.show()
		hbox1.set_spacing(5)
		hbox1.set_border_width(4)
	
		self.SearchEntry = gtk.Entry()
		self.SearchEntry.set_text("")
		self.SearchEntry.set_editable(True)
		self.SearchEntry.connect("activate", self.DoSearch)
		self.SearchEntry.show()
		hbox1.pack_start(self.SearchEntry, True, True, 0)
	
		self.GlobalSearch = gtk.RadioButton()
		self.GlobalSearch.set_active(True)
		self.GlobalSearch.set_label(("Global"))
		self.GlobalSearch.show()
	
		hbox1.pack_start(self.GlobalSearch, False, False, 0)
	
		self.BuddySearch = gtk.RadioButton(self.GlobalSearch)
		self.BuddySearch.set_active(False)
		self.BuddySearch.set_label(("Buddies"))
		self.BuddySearch.show()
	
		hbox1.pack_start(self.BuddySearch, False, False, 0)
	
		self.RoomSearch = gtk.RadioButton(self.GlobalSearch)
		self.RoomSearch.set_active(False)
		self.RoomSearch.set_label(("Rooms"))
		self.RoomSearch.show()
	
		hbox1.pack_start(self.RoomSearch, False, False, 0)
	
		self.SearchButton = self.CreateIconButton(gtk.STOCK_FIND, "stock", self.DoSearch, "Search")
		
	
		hbox1.pack_start(self.SearchButton, False, False, 0)
	
		self.SearchVbox.pack_start(hbox1, False, False, 0)
		self.SearchVbox.pack_start(self.Searches)
		
		# User lists Construction
		self.userlists = ListsOfUsers(self)
		
		# Userinfo Construction
		
		self.userinfovbox = gtk.VBox(False, 0)
		self.userinfovbox.show()
		self.userinfovbox.set_spacing(0)

		self.userinfos = UserInfos(self)
	
		self.hbox21 = gtk.HBox(False, 5)
		self.hbox21.show()
		self.hbox21.set_spacing(5)
		self.hbox21.set_border_width(5)
		
		self.UserinfoEntry = gtk.Entry()
		self.UserinfoEntry.set_text("")
		self.UserinfoEntry.set_editable(True)
		self.UserinfoEntry.show()
		self.UserinfoEntry.set_visibility(True)
		self.hbox21.pack_start(self.UserinfoEntry, False, True, 0)
		
		self.sUserinfoButton = self.CreateIconButton(gtk.STOCK_JUMP_TO, "stock", self.OnGetUserInfo, _("Get UserInfo"))
		
	
		self.hbox21.pack_start(self.sUserinfoButton, False, False, 0)
	
		self.userinfovbox.pack_start(self.hbox21, False, True, 0)
		
		self.UserinfoEntry.connect("activate", self.OnGetUserInfo)
		self.userinfovbox.pack_start(self.userinfos, True, True, 0)
		# User Browse Construction
		self.userbrowsevbox = gtk.VBox(False, 0)
		self.userbrowsevbox.show()
		self.userbrowsevbox.set_spacing(0)
		
		self.userbrowses = UserBrowses(self)
		
		
	
		self.hbox22 = gtk.HBox(False, 5)
		self.hbox22.show()
		self.hbox22.set_spacing(5)
		self.hbox22.set_border_width(5)
	
		
	
		self.SharesEntry = gtk.Entry()
		self.SharesEntry.set_text("")
		self.SharesEntry.set_editable(True)
		self.SharesEntry.show()
		self.SharesEntry.set_visibility(True)
		self.hbox22.pack_start(self.SharesEntry, False, True, 0)
		
		self.sSharesButton = self.CreateIconButton(gtk.STOCK_JUMP_TO, "stock", self.OnGetShares, _("Browse Shares"))
	
		self.hbox22.pack_start(self.sSharesButton, False, False, 0)
		self.SharesEntry.connect("activate", self.OnGetShares)

		self.userbrowsevbox.pack_start(self.hbox22, False, True, 0)
		self.userbrowsevbox.pack_start(self.userbrowses, True, True, 0)
		# Room List Construction
		## Recommendations and Interests
		
		self.Recommendations = Recommendations(self)
		
		#
		#
		# Add tabs to Notebook
		self.ChatRoomLabel = ImageLabel(_("Chat Rooms"), self.images["empty"])
		self.notebook_outside.append_page(self.ChatRoomsVbox, self.ChatRoomLabel)
		
		self.PrivateChatLabel = ImageLabel(_("Private Chat"), self.images["empty"])
		self.notebook_outside.append_page(self.privatevbox, self.PrivateChatLabel)
		
		self.TransfersLabel = ImageLabel(_("Transfers"), self.images["empty"])
		self.notebook_outside.append_page(self.notebook_transfers, self.TransfersLabel)
		
		self.SearchLabel = ImageLabel(_("Search"), self.images["empty"])
		self.notebook_outside.append_page(self.SearchVbox, self.SearchLabel)
		
		self.UserInfoLabel = ImageLabel(_("User Info"), self.images["empty"])
		self.notebook_outside.append_page(self.userinfovbox, self.UserInfoLabel)
		
		self.UserBrowseLabel = ImageLabel(_("User Browse"), self.images["empty"])
		self.notebook_outside.append_page(self.userbrowsevbox, self.UserBrowseLabel )
		
		self.UserListsLabel = ImageLabel(_("Users & Interests"), self.images["empty"])
		self.notebook_outside.append_page(self.userlists, self.UserListsLabel)
		
		self.RoomListLabel = ImageLabel(_("Room List"), self.images["empty"])
		self.notebook_outside.append_page(self.notebook_roomlist, self.RoomListLabel)
		
		#self.InterestsLabel = ImageLabel(_("Interests"), self.images["empty"])
		#self.notebook_outside.append_page(self.Recommendations.Main, self.InterestsLabel)
		self.userlists.append_page(self.Recommendations.Main, _("Interests"))
		self.notebook_outside.show()
		self.notebook_outside.connect("switch_page", self.OnSwitchPage)

	def OnSwitchPage(self, notebook, page, page_nr):
		l = [self.ChatRoomLabel, self.PrivateChatLabel, self.TransfersLabel, self.SearchLabel, self.UserInfoLabel, self.UserBrowseLabel, self.UserListsLabel, self.RoomListLabel, ][page_nr]
		n = [self.ChatRooms, self.PrivateChats, None, self.Searches, self.userinfos, self.userbrowses, self.userlists, None][page_nr]
		self.current_tab = l
		if l is not None:
			l.set_image(self.images["empty"])
		if n is not None:
			#print n
			n.popup_disable()
			n.popup_enable()
			if n.get_current_page() != -1:
				n.dismiss_icon(n, None, n.get_current_page())

		if page_nr == 0 and self.ChatRooms:
			p = n.get_current_page()
			self.ChatRooms.OnSwitchPage(n, None, p, 1)
		elif page_nr == 1:
			p = n.get_current_page()
			self.PrivateChats.OnSwitchPage(n, None, p, 1)
			
	def RequestIcon(self, tablabel):
		if tablabel == self.PrivateChatLabel and not self.got_focus:
			self.MurmurWindow.set_icon(self.images["online"])
		if self.current_tab != tablabel:
			tablabel.set_image(self.images["online"])
			
	def OnFocusIn(self, widget, event):
		self.MurmurWindow.set_icon(self.images["icon"])
		self.got_focus = True
	
	def OnFocusOut(self, widget, event):
		self.got_focus = False	
		
	def OnSelectionGet(self, widget, data, info, timestamp):
		data.set_text(self.clip_data, -1)
	
	def GetCompletion(self, part, list):
		matches = []
		for match in list:
			if match in matches:
				continue
			if match[:len(part)] == part and len(match) > len(part):
				matches.append(match)
		
		if len(matches) == 0:
			return "", 0
		elif len(matches) == 1:
			return matches[0][len(part):], 1
		else:
			prefix = matches[0]
			for item in matches:
				for i in range(len(prefix)):
					if prefix[:i+1] != item[:i+1]:
						prefix = prefix[:i]
						break
			return prefix[len(part):], 0
					
	def Humanize(self, size):
		if size is None:
			return None

		try:
			s = int(size)
			if s >= 1000*1024*1024:
				r = _("%.2f GB") % ((float(s) / (1024.0*1024.0*1024.0)))
			elif s >= 1000*1024:
				r = _("%.2f MB") % ((float(s) / (1024.0*1024.0)))
			elif s >= 1000:
				r = _("%.2f KB") % ((float(s) / 1024.0))
			else:
				r = str(size)
			return r
		except:
			return size 
		
			
	def DoSearch(self, widget):
		
		query = self.SearchEntry.get_text()
		if query == "":
			return
		elif query.isspace():
			return
		elif len(query) < 3:
			return
		if self.GlobalSearch.get_active():
			self.Networking.Search(0, query)
		elif self.BuddySearch.get_active():
			self.Networking.Search(1, query)
		elif self.RoomSearch.get_active():
			self.Networking.Search(2, query)
		self.SearchEntry.set_text("")
		
	def OnSearch(self, widget):
		self.notebook_outside.set_current_page(3)
		
	def OnGetShares(self, widget):
		self.GetShares(self.SharesEntry.get_text())
		self.SharesEntry.set_text("")
		
	def OnGetUserInfo(self, widget):
		self.GetUserInfo(self.UserinfoEntry.get_text())
		self.UserinfoEntry.set_text("")
		
	def OnGetPrivateChat(self, widget):
		self.GetPrivateChat(self.PrivateChatEntry.get_text())
		self.PrivateChatEntry.set_text("")
			
	def GetUserInfo(self, user):
		if user != "" and not user.isspace():
			self.Networking.UserInfo(user)
			if user not in self.user_stats:
				self.Networking.PeerExists(user)
	def OnUserInfo(self, widget):
		self.notebook_outside.set_current_page(4)
		
	def GetIPAddress(self, user):
		if user not in self.ip_requested and user != "" and not user.isspace():
			self.ip_requested.append(user)
			self.Networking.PeerAddress(user)
			
	def GetPrivateChat(self, user):
		if user != "" and not user.isspace():
			self.PrivateChats.SendMessage(user)
			if user not in self.user_stats:
				self.Networking.PeerExists(user)
	def GetShares(self, user):
		if user != "" and not user.isspace():
			self.Networking.UserShares(user)
			if user not in self.user_stats:
				self.Networking.PeerExists(user)
	def OnUserShares(self, widget):
		self.notebook_outside.set_current_page(5)
	def JoinARoom(self, room):

		if room != None and room != "":
			self.Networking.JoinRoom(room)
			
	def RoomLeave(self, room):

		if room != None and room != "":
			if room in self.ChatRooms.joinedrooms:
				self.Networking.LeaveRoom(room)
				
	def CreateMainMenu(self):
		
		MainMenu = gtk.MenuBar()
		
		
		# File Menu
		MenuFile = gtk.Menu()
		ItemFile = gtk.MenuItem(("_File"))
		ItemFile.show()
		
		# Museek Sub-Menu
		MenuMuseek = gtk.Menu()
		ItemMuseek = gtk.MenuItem("_Museek")
		
		ItemConnect = gtk.ImageMenuItem("_Connect")
		ItemConnect.connect_object("activate", self.connect_process, None)
		ItemConnect.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("C"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
        	ItemConnect.set_image(gtk.image_new_from_stock(gtk.STOCK_CONNECT, gtk.ICON_SIZE_MENU))
		ItemConnect.show()
		
		ItemDisconnect = gtk.ImageMenuItem("_Disconnect")
		ItemDisconnect.connect_object("activate", self.disconnect, "disconnect")
		ItemDisconnect.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("D"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemDisconnect.set_image(gtk.image_new_from_stock(gtk.STOCK_DISCONNECT, gtk.ICON_SIZE_MENU))
		ItemDisconnect.show()
		
		ItemSettings = gtk.ImageMenuItem("_Settings")
		ItemSettings.connect_object("activate", self.SettingsWindow, "settings")
		ItemSettings.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("S"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemSettings.set_image(gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU))
		ItemSettings.show()
		
		MenuMuseek.append(ItemConnect)
		MenuMuseek.append(ItemDisconnect)
		MenuMuseek.append(ItemSettings)

		ItemMuseek.set_submenu(MenuMuseek)
		ItemMuseek.show()
		
		# Continuation of File Menu
		self.ItemTray = ItemTray = gtk.CheckMenuItem("Hide _Trayapp")
		
		if self.Config["murmur"]["trayapp"] == "no":
			ItemTray.set_active(True)
			
		else:
			ItemTray.set_active(False)
		ItemTray.connect_object("activate", self.TrayApp.trayapp, "tray")
		ItemTray.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("T"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemTray.show()
		
		self.ItemAway = gtk.ImageMenuItem("Toggle Away")
		self.ItemAway.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("A"), gtk.gdk.MOD1_MASK , gtk.ACCEL_VISIBLE)
		self.ItemAway.connect("activate", self.away_toggle)
		img = gtk.Image()
		img.set_from_pixbuf(self.images["away"])
		self.ItemAway.set_image(img)
		self.ItemAway.show()
		
		self.ItemLogWindow = ItemLogWindow = gtk.CheckMenuItem(_("Hide log _window"))
		ItemLogWindow.set_active(False)
		ItemLogWindow.connect("activate", self.ToggleLogWindow, "")
		ItemLogWindow.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("W"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemLogWindow.show()

		ItemQuit = gtk.ImageMenuItem("_Quit Murmur Chat")
		ItemQuit.connect("activate", self.window_quit, "")
		ItemQuit.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("Q"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemQuit.set_image(gtk.image_new_from_stock(gtk.STOCK_QUIT, gtk.ICON_SIZE_MENU))
		ItemQuit.show()
		
		MenuFile.append(ItemMuseek)
		MenuFile.append(ItemTray)
		MenuFile.append(self.ItemAway)
		MenuFile.append(ItemLogWindow)
		MenuFile.append(ItemQuit)
		MenuFile.show()
		
		ItemFile.set_submenu(MenuFile)
		
		
		# Room Menu
		MenuRooms = gtk.Menu()
		
		ItemRooms = gtk.MenuItem(("_Rooms"))
		
		
		ItemJoinRoom = gtk.ImageMenuItem("_Join Room")
		ItemJoinRoom.connect("activate", self.PopupEntryJoinRoom, "")
		ItemJoinRoom.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("J"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemJoinRoom.set_image(gtk.image_new_from_stock(gtk.STOCK_JUMP_TO, gtk.ICON_SIZE_MENU))
		ItemJoinRoom.show()
		
		ItemLeaveRoom = gtk.ImageMenuItem("_Leave Room")
		ItemLeaveRoom.connect("activate", self.PopupEntryLeaveRoom, "")
		ItemLeaveRoom.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("L"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemLeaveRoom.set_image(gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU))
		ItemLeaveRoom.show()
		
		MenuRooms.append(ItemJoinRoom)
		MenuRooms.append(ItemLeaveRoom)
		
		ItemRooms.set_submenu(MenuRooms)
		ItemRooms.show()
		
		# Modes Menu
		ItemUsers = gtk.MenuItem(("_Users"))
		ItemUsers.show()
		MenuUsers = gtk.Menu()
		
		ItemPrivate = gtk.ImageMenuItem("Send _Private Message to a User")
		ItemPrivate.connect("activate", self.PopupEntryPrivate, "")
		ItemPrivate.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("P"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemPrivate.set_image(gtk.image_new_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_MENU))
		ItemPrivate.show()

		ItemIP = gtk.ImageMenuItem("Lookup a User's IP Address")
		ItemIP.connect_object("activate", self.LookupIP, "file.ip")
		ItemIP.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("I"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemIP.set_image(gtk.image_new_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU))
		ItemIP.show()
		
		ItemUserInfo = gtk.ImageMenuItem("Lookup a User's Info")
		ItemUserInfo.connect_object("activate", self.LookupUserInfo, "file.userinfo")
		ItemUserInfo.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("E"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemUserInfo.set_image(gtk.image_new_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_MENU))
		ItemUserInfo.show()
		
		ItemBrowse = gtk.ImageMenuItem("Browse a User's Shares")
		ItemBrowse.connect_object("activate", self.LookupUserShares, "file.browse")
		ItemBrowse.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("B"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemBrowse.set_image(gtk.image_new_from_stock(gtk.STOCK_HARDDISK, gtk.ICON_SIZE_MENU))
		ItemBrowse.show()
		
		MenuUsers.append(ItemPrivate)
		#MenuUsers.append(ItemStats)
		MenuUsers.append(ItemIP)
		MenuUsers.append(ItemUserInfo)
		MenuUsers.append(ItemBrowse)
		
		ItemUsers.set_submenu(MenuUsers)
		
		# Help Menu
		ItemHelp = gtk.MenuItem(("_Help"))
		ItemHelp.show()
	
		MenuHelp = gtk.Menu()
	
		ItemAbout = gtk.ImageMenuItem(("_About"))
		ItemAbout.connect("activate", self.about)
		ItemAbout.add_accelerator("activate", self.accel_group, gtk.gdk.keyval_from_name("F1"), gtk.gdk.MOD1_MASK, gtk.ACCEL_VISIBLE)
		ItemAbout.set_image(gtk.image_new_from_stock(gtk.STOCK_HELP, gtk.ICON_SIZE_MENU))
		ItemAbout.show()
	
		MenuHelp.append(ItemAbout)
		
		ChatCommandsItem = gtk.ImageMenuItem(("_Chat Commands"))
		ChatCommandsItem.connect("activate", self.ChatRoomCommands)
		ChatCommandsItem.set_image(gtk.image_new_from_stock(gtk.STOCK_HELP, gtk.ICON_SIZE_MENU))
		ChatCommandsItem.show()
		MenuHelp.append(ChatCommandsItem)
		

		SharesCommandsItem = gtk.ImageMenuItem(("_Shares Commands"))
		SharesCommandsItem.connect("activate", self.SharesCommands)
		SharesCommandsItem.set_image(gtk.image_new_from_stock(gtk.STOCK_HELP, gtk.ICON_SIZE_MENU))
		SharesCommandsItem.show()
		MenuHelp.append(SharesCommandsItem)
		
		
		MenuHelp.show()

		ItemHelp.set_submenu(MenuHelp)
		
		# Arrange Main Menu
		MainMenu.append(ItemFile)
		MainMenu.append(ItemRooms)
		MainMenu.append(ItemUsers)
		MainMenu.append(ItemHelp)
		MainMenu.show()
		return MainMenu


Murmur()

mainloop = gobject.MainLoop()
mainloop.run()

