## $Id: addresslist.py,v 1.5 2001/05/14 12:06:31 kjetilja Exp $

## System modules
from gtk import *
from gnome.ui import *



##
##
## Main address list class
##
##
class AddressListWindow:
    ##
    ## Method __init__ (self, folder instance, edit instace)
    ##
    ##    Address list widget constructor.
    ##
    ##
    def __init__(self, fld, edit=None, parent=None):
        self.fld = fld
        self.edit = edit
        self.prefs = self.fld.prefs
        self.win = GnomeDialog(':Pygmy - Address List',
                               'Add', 'Edit', 'Remove',
                               STOCK_BUTTON_OK, STOCK_BUTTON_CANCEL)
        if parent == None:
            self.win.set_parent(self.fld.win)
        else:
            self.win.set_parent(parent)            
        self.vbox = self.win.vbox
        self.win.connect('clicked', self.handle_callbacks)
	self.win.connect('delete_event', self.destroy)
	self.win.connect('destroy', self.destroy)
        self.init_addrlist()
        self.win.show()


    ##
    ## Method handle_callbacks (self, button, no)
    ##
    ##    Handle callbacks for the action buttons.
    ##
    ##
    def handle_callbacks(self, button, no):
        if no == 0:
            self.add_callback(button)
        elif no == 1:
            self.edit_callback(button)
        elif no == 2:
            self.delete_callback(button)
        elif no == 3:
            self.ok_callback(button)
        elif no == 4:
            self.destroy()
        else:
            print "addresslist -- got unknown button callback event"



    ##
    ## Method init_addrlist (self)
    ##
    ##    Address list.
    ##
    ##
    def init_addrlist(self):
        self.adisp = GtkCList(2, ['Name', 'Email Address'])
        self.adisp.connect("click_column", self.clickcolumn)
        self.adisp.connect("select_row", self.selectrow)
        # Widget attributes
        self.adisp.set_selection_mode(SELECTION_EXTENDED)
        self.adisp.set_column_width(0, 150)
        self.adisp.set_column_width(1, 150)
        self.adisp.set_border_width(2)
	self.adisp.set_usize(0, 256)
        # Add scrollbars
        swin = GtkScrolledWindow()
        swin.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
        self.vbox.pack_start(swin)
        swin.add(self.adisp)
        swin.show()
        self.adisp.show()

        # Store reference to addresslist
        import marshal
        try:
            self.adrlist = marshal.load( open(self.prefs.alistfile) )
        except:
            self.adrlist = {}

        # Inject entries into the listview
        for name in self.adrlist.keys():
            self.adisp.append( (name, self.adrlist[name]) )
        self.sort()


    ## Shortcut function
    def sort(self, c=0):
        self.adisp.set_sort_column(c)
        self.adisp.set_sort_type(SORT_ASCENDING)
        self.adisp.sort()

    ## Sort the address list alphabetically when clicked
    def clickcolumn(self, clist, c):
        self.sort(c)
        
    ## Need this one to catch double clicks on a list item.
    def selectrow(self, clist, r, c, event):
        if hasattr(event, 'type'):
            # Check for double clicks on the list item
            if event.type == 5: 
                # Launch a edit box (should something else happen?)
                self.edit_callback()


    ##
    ## Method delete_callback (self, button)
    ##
    ##    Callback for the Delete button.
    ##
    ##
    def delete_callback(self, button):
        import string
        if self.adisp.selection == []:
            return
        sel = self.adisp.selection
        self.delname = {}
        for index in sel:
            self.delname[index] = self.adisp.get_text(index,0)
	l = GtkLabel("Confirm deletion:\n "+ \
                     string.join(self.delname.values(), "\n"))
	l.show()
        v = GnomeDialog('Delete', 'Ok', 'Cancel')
        v.set_parent(self.win)
        v.vbox.pack_start(l)
        v.connect('clicked', self.do_delete)
        v.show()


    ##
    ## Method do_delete (self, button, no)
    ##
    ##    Callback for the Ok button Combobox in Delete.
    ##
    ##
    def do_delete(self, button, no):
        if no == 0:
            # Ok button
            for index in self.delname.keys():
                self.adisp.remove(index)
                del self.adrlist[self.delname[index]]
            button.destroy()
        elif no == 1:
            # Cancel button
            button.destroy()


    ##
    ## Method edit_callback (self, button)
    ##
    ##    Callback for the Edit button and row doubleclicks.
    ##
    ##
    def edit_callback(self, button=None):
        if self.adisp.selection == []:
            return
        index = self.adisp.selection[0]
        self.oldname = self.adisp.get_text(index,0)
        self.oldmail = self.adisp.get_text(index,1)

	ln = GtkLabel("Enter new name:")
	ln.show()
	self.nameentry = GtkEntry()
        self.nameentry.show()
        self.nameentry.set_text(self.oldname)
	le = GtkLabel("Enter new email address:")
	le.show()
	self.mailentry = GtkEntry()
        self.mailentry.show()
        self.mailentry.set_text(self.oldmail)
        v = GnomeDialog('Edit', 'Ok', 'Cancel')
        v.set_parent(self.win)
        v.vbox.pack_start(ln)
        v.vbox.pack_start(self.nameentry)
        v.vbox.pack_start(le)
        v.vbox.pack_start(self.mailentry)
        v.connect('clicked', self.do_edit)        
        v.show()
        self.nameentry.grab_focus()


    ##
    ## Method do_edit (self, button, no)
    ##
    ##    Callback for the Ok button Combobox in Edit.
    ##
    ##
    def do_edit(self, button, no):
        if no == 0:
            # Ok button
            name = self.nameentry.get_text()
            mail = self.mailentry.get_text()
            if name == '' or mail == '':
                # User has given empty input strings, do nothing
                button.destroy()
                return
            # Update display
            self.adisp.set_text(self.adisp.selection[0], 0, name)
            self.adisp.set_text(self.adisp.selection[0], 1, mail)

            # Update internal list
            self.adrlist[name] = mail
            if self.oldname in self.adrlist.keys() and \
               self.oldname != name:
                del self.adrlist[self.oldname]
            button.destroy()
        elif no == 1:
            # Cancel button
            button.destroy()

    

    ##
    ## Method do_add (self, button, no)
    ##
    ##    Callback for the Ok button Combobox in Add.
    ##
    ##
    def do_add(self, button, no):
        if no == 0:
            # Ok button
            name = self.nameentry.get_text()
            mail = self.mailentry.get_text()
            if name in self.adrlist.keys() or name == '' or mail == '':
                # User has input an existing name, do nothing
                button.destroy()
                return
            # Append to display list
            self.adisp.append((name, mail))
            # Append to list of names to be created at commit
            self.adrlist[name] = mail
            # Remove entry from the msgwin stuff
            try: self.fld.msgwin.mail_field = ''
            except: pass
            button.destroy()
        elif no == 1:
            # Cancel button
            button.destroy()

    def add_name_and_edit(self, name, mail):
        ln = GtkLabel("Edit new name:")
	ln.show()
	self.nameentry = GtkEntry()
        self.nameentry.show()
        self.nameentry.set_text(name or '')
	le = GtkLabel("Edit new email address:")
	le.show()
	self.mailentry = GtkEntry()
        self.mailentry.show()
        self.mailentry.set_text(mail or '')
        v = GnomeDialog('Edit', 'Ok', 'Cancel')
        v.set_parent(self.win)
        v.vbox.pack_start(ln)
        v.vbox.pack_start(self.nameentry)
        v.vbox.pack_start(le)
        v.vbox.pack_start(self.mailentry)
        v.connect('clicked', self.do_add)
        v.show()
        self.nameentry.grab_focus()
        
    ##
    ## Method add_callback (self, button)
    ##
    ##    Callback for the Add button.
    ##
    ##
    def add_callback(self, button):
	ln = GtkLabel("Enter name:")
	ln.show()
	self.nameentry = GtkEntry()
        self.nameentry.show()
	le = GtkLabel("Enter email address:")
	le.show()
	self.mailentry = GtkEntry()
        self.mailentry.show()
        v = GnomeDialog('Add', 'Ok', 'Cancel')
        v.set_parent(self.win)
        v.vbox.pack_start(ln)
        v.vbox.pack_start(self.nameentry)
        v.vbox.pack_start(le)
        v.vbox.pack_start(self.mailentry)
        v.connect('clicked', self.do_add)
        v.show()
        self.nameentry.grab_focus()

        # If the message view window is up, use from: field contents
        # to fill the email address information
        if self.fld.msgwin and self.fld.msgwin.mail_field != '':
            self.mailentry.set_text(self.fld.msgwin.mail_field)

    ## Just to short-circuit the window delete/destroy events
    def destroy(self, foo=None, bar=None):
        self.fld.adrlist_active = 0
        self.win.destroy()

    ##
    ## Method ok_callback ()
    ##
    def ok_callback(self, button):
        """
        Callback for the Ok button.  Commit changes.
        """

        import marshal

        # Dump address list to disk first
        marshal.dump(self.adrlist, open(self.prefs.alistfile, 'w'))

        # If invoked from the edit window, insert selected stuff
        if self.adisp.selection != []:
            index = self.adisp.selection
            # Check if we were invoked by the edit window buttons
            if not self.edit:
                self.destroy()
                return
            # Evidently we were -- do the business
            if self.edit.field == 'to':
                # Add to To: field
                if self.edit.e1.get_text() == '':  pre = ''
                else:  pre = ', '
                for entry in self.adisp.selection:
                    self.edit.e1.append_text(pre+self.adisp.get_text(entry,1))
                    pre = ', '
            elif self.edit.field == 'cc':
                # Add to CC: field
                if self.edit.e2.get_text() == '':  pre = ''
                else:  pre = ', '
                for entry in self.adisp.selection:
                    self.edit.e2.append_text(pre+self.adisp.get_text(entry,1))
                    pre = ', '
            elif self.edit.field == 'bcc':
                # Add to Bcc: field
                if self.edit.e4.get_text() == '':  pre = ''
                else:  pre = ', '
                for entry in self.adisp.selection:
                    self.edit.e4.append_text(pre+self.adisp.get_text(entry,1))
                    pre = ', '


        # Destroy ourselves
        self.destroy()
