# File: mailbox.py
# Purpose: pop3 inbox class

import socket
import string
import gtk
import cPickle

from pyneheaders import *
import mail_recv
from mail_recv import *
import mail_send
from mail_send import *
from superbox import *
import boxformats
import boxformats.configbox
from ptk.big_edit_box import *
import pynei18n
from boxtypes.net_exceptions import *
import msgfilter
import personality
import ptk.personalitybox
import ptk.misc_widgets

class mailbox(superbox):
	"""
	Pop3 inbox.
	"""
	def get_flags(self):
		flags = BOX_ISDELETEABLE | BOX_MAKE_NEW_MSG | \
		       BOX_REPLY_SINGLE | BOX_REPLY_GROUP | \
		       BOX_REPLY_FORWARD | BOX_DEL_MESSAGE | \
		       BOX_IMPORT_TO

		if self.recv_type != mail_recv.MAIL_RECV_NONE:
			return flags | BOX_UPDATE_METHOD
		else:
			return flags
	
	def save(self, user):

		tosave = {}

		def _saveme(key, tosave=tosave, self=self):
			tosave[key] = self.__dict__[key]

		_saveme("uid")
		_saveme("name")
		_saveme("opts")
		_saveme("recv_type")
		_saveme("send_type")
		_saveme("recv_conf")
		_saveme("send_conf")
		_saveme("personalities")
		_saveme("default_personality")
		_saveme("collection_threads")
		_saveme("expire_after")
		_saveme("export_format")
		_saveme("collect_policy")
		_saveme("filters")
		_saveme("num_unread")

		f = open(self.uid+".fol", "w")

		cPickle.dump(ver_stamp, f, 1)
		cPickle.dump("MAILBOX", f, 1)
		cPickle.dump(tosave, f, 1)

		f.close()

	def __init__(self, user, uid):
		self.load(user, uid)

	def load(self, user, uid):
		"""
		Create new pop inbox.
		"""
		self.load_box (user, uid)

		def _ifmissing(key, value, self=self):
			if not self.__dict__.has_key(key):
				self.__dict__[key] = value

		_ifmissing("uid", uid)
		_ifmissing("name", _("Mailbox"))
		_ifmissing("opts", 0)

		_ifmissing("recv_type", mail_recv.MAIL_RECV_POP3)
		_ifmissing("send_type", mail_send.MAIL_SEND_SMTP)
		
		_ifmissing("recv_conf", { "server": "pop.someisp.com",
				    "port": 110,
				    "username": "",
				    "password": "",
				    "auth": 0 } )
		_ifmissing("send_conf", { "server": "smtp.someisp.com",
				     "port": 25,
				     "username": "",
				     "password": "",
				     "auth": 0 } )
		# Keys in user.personalities dict
		_ifmissing("personalities", [])
		
		# Add a default personality
		if not self.__dict__.has_key("default_personality"):
			p = personality.personality(self.name+" default")
			p.uid = user.get_personality_uid()
			user.personalities[p.uid] = p
			self.personalities.append(p.uid)
			self.default_personality = p.uid
	
		_ifmissing("collection_threads", 1)
		_ifmissing("expire_after", None)
		_ifmissing("export_format", (boxformats.BF_FLATFILEBOX, None))
		
		# server things
		_ifmissing("collect_policy", (SERVER_DELETE, ""))

		_ifmissing("filters", [])
		_ifmissing("num_unread", 0)

		# sub-folders
		self.contents = []
		self.startup(user)

	def startup(self, user):
		"""
		Get an io module for loading/saving articles
		"""
		i = self.export_format[0]
		# this is a pretty piece of code :-)
		bf_class = boxformats.__dict__[boxformats.__all__[i]]. \
			   __dict__[boxformats.__all__[i]]
		self._io = bf_class(user, self)
		# get recv and send server types
		i = self.recv_type
		self.recv_server = mail_recv.__dict__[mail_recv.__all__[i]]
		i = self.send_type
		self.send_server = mail_send.__dict__[mail_send.__all__[i]]
		self.messages = self._io.get_contents()

	def getstats(self):
		"""
		Returns message to be put in 'items' field of mailbox view.
		"""
		#return (len(self.messages),)
		return (str (self.num_unread) + " ("+ str(len(self.messages)) + ")",)

	def get_menu(self):
		"""
		This folder type specific options.
		"""
		return []

	def menu_chosen(self, _a, choice):
		return

	def get_connection(self, recv=0, no_connection=0):
		"""
		Return a connection object. if pop=0: smtp, pop=1: pop3.
		"""
		if recv == 0:
			# establish smtp connection
			c = self.send_server.get_connection(self.send_conf)
			return c
		else:
			# establish pop3 connection
			c = self.recv_server.get_connection(self.recv_conf, no_connection)
			return c

	def setup(self, user, parent_win):
		"""
		Configure a mailbox.
		"""
		import msgfilter
		win = gtk.Window()
		win.set_title(self.name+" "+_("Setup"))
		win.set_transient_for(parent_win)

		box = gtk.VBox()
		box.set_border_width(5)
		win.add(box)
		box.show()

		notebook = gtk.Notebook()
		notebook.set_tab_pos(gtk.POS_TOP)
		box.pack_start(notebook)
		notebook.show()
	
		# First page: Misc settings
		box1 = gtk.VBox(spacing=5)

		settings_box0 = big_edit_box( self,
		      ( ("name", _("Name:"), VAR_TYPE_STRING, 0, 0),
		        ("expire_after", _("Expire after (days):"), VAR_TYPE_INTEGER, 0, None),
			("collection_threads", _("Download threads:"), VAR_TYPE_INTEGER, 0, 4),
			("opts", _("Thread messages"), VAR_TYPE_PACKED_BIT_BOOLEAN, 0, OPT_THREAD) )
		)

		box1.pack_start(settings_box0, expand=False)
		settings_box0.show()
		
		policybox = msgfilter.policy_editbox(self)
		box1.pack_start(policybox, expand=False)
		policybox.show()
		
		
		def _update_buttons ():
			self.send_config_button.set_sensitive (self.send_server.setup != None)
			self.recv_config_button.set_sensitive (self.recv_server.setup != None)
		def _change_send_server(item, self=self):
			type = mail_send.__all__[send_combo.get_active ()]
			# if changed
			if mail_send.__all__.index(type) != self.send_type:
				self.send_type = mail_send.__all__.index(type)
				self.send_server = mail_send.__dict__[mail_send.__all__[self.send_type]]
				self.send_server.fix_defaults(self.send_conf)
			_update_buttons ()
		def _config_send_server(_button, self=self):
			self.send_server.setup(self, self.send_conf, win)
		def _config_recv_server(_button, self=self):
			self.recv_server.setup(self, self.recv_conf, win)
				
		def _change_recv_server(item, self=self):
			type = mail_recv.__all__[recv_combo.get_active ()]
			# if changed
			if mail_recv.__all__.index(type) != self.recv_type:
				self.recv_type = mail_recv.__all__.index(type)
				self.recv_server = mail_recv.__dict__[mail_recv.__all__[self.recv_type]]
				self.recv_server.fix_defaults(self.recv_conf)
			_update_buttons ()

		table = gtk.Table(3,2)
		table.set_row_spacings(5)
		table.set_col_spacings(5)
		box1.pack_start(table, expand=False)
		table.show()
		
		label = gtk.Label(_("Send server"))
		table.attach(label, 0,1, 0,1)
		label.show()
		
		send_combo = gtk.combo_box_new_text ()
		for i in range (0, len (mail_send.__all__)):
			send_combo.append_text (mail_send.names[i])
		send_combo.set_active (self.send_type)
		send_combo.connect ("changed", _change_send_server)
		table.attach (send_combo, 1,2, 0,1)
		send_combo.show ()
		
		self.send_config_button = gtk.Button(_("Configure"))
		self.send_config_button.connect("clicked", _config_send_server)
		table.attach(self.send_config_button, 2,3, 0,1)
		self.send_config_button.show()
		
		label = gtk.Label(_("Receive server"))
		table.attach(label, 0,1, 1,2)
		label.show()
		
		recv_combo = gtk.combo_box_new_text ()
		for i in range (0, len (mail_recv.names)):
			recv_combo.append_text (mail_recv.names[i])
		recv_combo.set_active (self.recv_type)
		recv_combo.connect ("changed", _change_recv_server)
		table.attach (recv_combo, 1,2, 1,2)
		recv_combo.show ()
		
		self.recv_config_button = gtk.Button(_("Configure"))
		self.recv_config_button.connect("clicked", _config_recv_server)
		table.attach(self.recv_config_button, 2,3, 1,2)
		self.recv_config_button.show()
		
		_update_buttons ()

		label = gtk.Label(_("Settings"))
		notebook.append_page(box1, label)
		box1.show()

		# 2nd page: personalities
		label = gtk.Label(_("Personalities"))
		personbox = ptk.personalitybox.personalitybox(self, user, win)
		notebook.append_page(personbox, label)
		personbox.show()

		# 3rd page: mail filters
		label = gtk.Label(_("Filters"))
		filterbox = msgfilter.filters_editlist(self, user)
		notebook.append_page(filterbox, label)
		filterbox.show()

		# 4th page: storage method
		label = gtk.Label(_("Mailbox Format"))
		formatbox = boxformats.configbox.configbox(self, user, win)
		notebook.append_page(formatbox, label)
		formatbox.show()

		def save_changes(_button, filterbox=filterbox, self=self, \
				user=user, win=win, settings_box0 = settings_box0, \
				policybox = policybox, personbox = personbox):
			# Extract info
			settings_box0.apply_changes()
			policybox.apply_changes()
			filterbox.apply_changes()
			personbox.apply_changes()
			# update folder list
			self.changed = 1
			# Save changes to disk
			self.save(user)
			user.update()

		def save_changes_close(_button, win=win, save_changes=save_changes):
			save_changes(_button)
			win.destroy()

		def _cancel(_button, win=win):
			win.destroy()

		# Seperator between entry boxes and buttons
		separator = gtk.HSeparator()
		box.pack_start(separator, expand=False)
		separator.show()

		# Buttons at bottom
		buttonbox = ptk.misc_widgets.MyButtonBox()
		box.pack_start(buttonbox, expand=False)
		buttonbox.show()

		button = gtk.Button(stock="gtk-ok")
		button.connect("clicked", save_changes_close)
		buttonbox.pack_end(button, expand=False)
		button.show()

		button = gtk.Button(stock="gtk-apply")
		button.connect("clicked", save_changes)
		buttonbox.pack_end(button, expand=False)
		button.show()

		button = gtk.Button(stock="gtk-cancel")
		button.connect("clicked", _cancel)
		buttonbox.pack_end(button, expand=False)
		button.show()

		win.show()

	def update(self, user, progressbar):
		"""
		Collect mail from server.
		"""
		import copy
		self.locked = 1
		# If no server is designated abort collection
		if self.recv_type == mail_recv.MAIL_RECV_NONE:
			del self.locked
			progressbar.finished()
			return

		usermsg = self.name+": "+_("Connecting to %s...") % self.recv_conf["server"]
		progressbar.log_msg(usermsg)
		progressbar.bar_msg(usermsg)

		def logfunc(msg, progressbar=progressbar):
			progressbar.log_msg(msg)
			progressbar.bar_msg(msg)
		
		num_threads = self.collection_threads
		
		try:
			# Connect to server
			servers = [ self.get_connection(recv=1) ]
			for i in range(1, num_threads):
				servers.append( self.get_connection(recv=1, no_connection=1) )
		except timeout_exception, e:
			logfunc(_("Error downloading %s: %s") % (self.name, str(e.args)))
			progressbar.bar_enable(False)
			progressbar.bar_pos(0.0)
			progressbar.finished()
			del self.locked
			return
		except auth_exception, e:
			logfunc(_("%s login incorrect") % self.name)
			progressbar.bar_enable(False)
			progressbar.bar_pos(0.0)
			progressbar.finished()
			del self.locked
			return

		# store nice listy thing of messages to collect
		self.pending_msgs = servers[0].get_msg_list()
		nummsgs = len( self.pending_msgs )

		articles = []
		for i in self.pending_msgs.keys():
			articles.append(i)

		def incfunc(self=self, progressbar=progressbar, start_num=nummsgs, articles=articles):
			"""
			Update progress bar.
			"""
			num_left = len(articles)
			if start_num == 0:
				progressbar.bar_pos(0.0)
			else:
				progressbar.bar_pos((start_num-num_left)/float(start_num))
			progressbar.bar_msg("%d/%d of " % ((start_num-num_left), start_num) + self.name)

		# Start collecting
		incfunc()
		self.recv_collect_threaded(user, servers, msgfilter.filter_collect, logfunc, incfunc, articles)

		for i in servers:
			i.close_connection()

		self.changed = 1
		progressbar.bar_enable(False)
		progressbar.bar_pos(0.0)
		progressbar.finished()
		user.queue_action(ACT_UPDATE)

		del self.pending_msgs
		del self.locked



syntax highlighted by Code2HTML, v. 0.9.1