#!/usr/bin/python2.2

import sys
import locale
PROGNAME="redhat-config-bind"
bindconf_dir = '/usr/share/'+PROGNAME
sys.path.append(bindconf_dir)

VERSION = "2.0.0"

if not "/usr/lib/python2.2/site-packages/rhpl" in sys.path:
    sys.path.append("/usr/lib/python2.2/site-packages/rhpl")

if not "/usr/lib64/python2.2/site-packages/rhpl" in sys.path:
    sys.path.append("/usr/lib64/python2.2/site-packages/rhpl")

try:
    import gtk
except RuntimeError,e:
    print "Unable to initialize graphical environment. Most likely cause of failure"
    print "is that the tool was not run using a graphical environment. Please either"
    print "start your graphical user interface or set your DISPLAY variable."
    print "Caught exception: %s" % e
    sys.exit(-1)
    
import Conf
import ConfNamed
import Zone
import gnome
import gnome.ui
import gtk.glade
import string
import signal
import os
import gettext
import re
import gobject
import socket

import FwdZone

from gtk import TRUE
from gtk import FALSE
from FwdZone import verify_delete
from FwdZone import generic_error_dialog
from FwdZone import add_dot
from Zone import TestError

hostname_pattern = '^[a-zA-Z0-9.\-@]+$'

#Columns for "bindconf_treeview"
COLUMN_PIXBUF=0
COLUMN_TEXT=1
COLUMN_DATA=2

#columns for "rev_zone_treeview", "fwd_zone_treeview"
COLUMN_PARENT=3

##
## I18N
## 

gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
#try:
#    gettext.install(PROGNAME, "/usr/share/locale", 1)
#except IOError:
#    print "IOError"
#    import __builtin__
#    __builtin__.__dict__['_'] = unicode
_=gettext.gettext

gnome.program_init (PROGNAME,VERSION)
gnome.app_version =VERSION
FORMALNAME=_("Domain Name Service")

##
## Global values
##

gladepath = "redhat-config-bind.glade"
if not os.path.exists(gladepath):
    gladepath = bindconf_dir + "/redhat-config-bind.glade"

gtk.glade.bindtextdomain(PROGNAME)
xml = gtk.glade.XML (gladepath, domain=PROGNAME)

image_domain = FwdZone.load_image("domain.png")
image_reverse = FwdZone.load_image("reverse.png")
image_slave = FwdZone.load_image("slave.png")
ROOTDIR=""
conf=Conf.ConfShellVar("/etc/sysconfig/named")
if conf.has_key("ROOTDIR"):
    ROOTDIR=conf.vars["ROOTDIR"]
cfg = ConfNamed.ConfNamed("/etc/named.conf",ROOTDIR)

class UpdateClass:
    UPDATE=FALSE
    def set(self,val):
        self.UPDATE=val
    def get(self):
        return self.UPDATE

update = UpdateClass()

fwd_zone_first_time = gtk.TRUE

def on_sort(model, iter1,iter2):
    try:
	obj1 = model.get_value (iter1, COLUMN_DATA)
	obj2 = model.get_value (iter2, COLUMN_DATA)
        if isinstance (obj1, tuple):
            return int(obj1[0]) - int(obj2[0])
        else:
            name1 =obj1.getName()
            name2 =obj2.getName()
    except ValueError:
	name1 = model.get_value (iter1, 1)
	name2 = model.get_value (iter2, 1)
        if name1 == None:
            return -1
        if name2 == None:
            return 1
    except:
        return 0
    return locale.strcoll(name1,name2)

##
## JRBs rewrite code.
##
class MyTreeModel(gtk.TreeStore):
    '''This class represents the model of a tree.  The iterators used
    to represent positions are converted to python objects when passed
    to the on_* methods.  This means you can use any python object to
    represent a node in the tree.  The None object represents a NULL
    iterator.

    In this tree, we use simple tuples to represent nodes, which also
    happen to be the tree paths for those nodes.  This model is a tree
    of depth 3 with 5 nodes at each level of the tree.  The values in
    the tree are just the string representations of the nodes.'''

    TREE_DEPTH = 4
    TREE_SIBLINGS = 5
    def __init__(self):
	'''constructor for the model.  Make sure you call
	PyTreeModel.__init__'''
	gtk.TreeStore.__init__(self, gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)
        self.set_sort_func(COLUMN_TEXT,on_sort)
    # the implementations for TreeModel methods are prefixed with on_
    def on_get_flags(self):
	'''returns the GtkTreeModelFlags for this particular type of model'''
	return 0
    def on_get_n_columns(self):
	'''returns the number of columns in the model'''
	return 1
    def on_get_column_type(self, index):
	'''returns the type of a column in the model'''
	return gobject.TYPE_STRING
    def on_get_path(self, node):
	'''returns the tree path (a tuple of indices at the various
	levels) for a particular node.'''
	return node
    def on_get_iter(self, path):
        '''returns the node corresponding to the given path.  In our
        case, the node is the path'''
        return path
    def on_get_value(self, node, column):
	'''returns the value stored in a particular column for the node'''
	assert column == 0
	return `node`
    def on_iter_next(self, node):
	'''returns the next node at this level of the tree'''
	if node[-1] == self.TREE_SIBLINGS - 1: # last node at level
	    return None
	return node[:-1] + (node[-1]+1,)
    def on_iter_children(self, node):
	'''returns the first child of this node'''
	if node == None: # top of tree
	    return (0,)
	if len(node) >= self.TREE_DEPTH: # no more levels
	    return None
	return node + (0,)
    def on_iter_has_child(self, node):
	'''returns true if this node has children'''
	return len(node) < self.TREE_DEPTH
    def on_iter_n_children(self, node):
	'''returns the number of children of this node'''
	if len(node) < self.TREE_DEPTH:
	    return self.TREE_SIBLINGS
	else:
	    return 0
    def on_iter_nth_child(self, node, n):
	'''returns the nth child of this node'''
        if node == None:
            return (n,)
	if len(node) < self.TREE_DEPTH and n < self.TREE_SIBLINGS:
	    return node + (n,)
	else:
	    return None
    def on_iter_parent(self, node):
	'''returns the parent of this node'''
	if len(node) == 0:
	    return None
	else:
	    return node[:-1]
    # the implementations for TreeModel methods are prefixed with on_
    def on_get_flags(self):
	'''returns the GtkTreeModelFlags for this particular type of model'''
	return 0
    def on_get_n_columns(self):
	'''returns the number of columns in the model'''
	return 1
    def on_get_column_type(self, index):
	'''returns the type of a column in the model'''
	return gobject.TYPE_STRING
    def on_get_path(self, node):
	'''returns the tree path (a tuple of indices at the various
	levels) for a particular node.'''
	return node
    def on_get_iter(self, path):
        '''returns the node corresponding to the given path.  In our
        case, the node is the path'''
        return path
    def on_get_value(self, node, column):
	'''returns the value stored in a particular column for the node'''
	assert column == 0
	return `node`
    def on_iter_next(self, node):
	'''returns the next node at this level of the tree'''
	if node[-1] == self.TREE_SIBLINGS - 1: # last node at level
	    return None
	return node[:-1] + (node[-1]+1,)
    def on_iter_children(self, node):
	'''returns the first child of this node'''
	if node == None: # top of tree
	    return (0,)
	if len(node) >= self.TREE_DEPTH: # no more levels
	    return None
	return node + (0,)
    def on_iter_has_child(self, node):
	'''returns true if this node has children'''
	return len(node) < self.TREE_DEPTH
    def on_iter_n_children(self, node):
	'''returns the number of children of this node'''
	if len(node) < self.TREE_DEPTH:
	    return self.TREE_SIBLINGS
	else:
	    return 0
    def on_iter_nth_child(self, node, n):
	'''returns the nth child of this node'''
        if node == None:
            return (n,)
	if len(node) < self.TREE_DEPTH and n < self.TREE_SIBLINGS:
	    return node + (n,)
	else:
	    return None
    def on_iter_parent(self, node):
	'''returns the parent of this node'''
	if len(node) == 0:
	    return None
	else:
	    return node[:-1]


##
## Callbacks
##
def on_bindconf_treeview_expand_row(tree_view, iter, *args):
    model = tree_view.get_model()
    zone = model.get_value (iter, COLUMN_DATA)

def on_alias_edit_button_click (*args):
    xml.get_widget ('a_edit_button').clicked ()

def on_zone_ns_add_button_clicked (clicked):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('zone_ns_treeview')
    selected = tree_view.get_selection().get_selected ()
    ns = FwdZone.NSProxy ()
    if ns.run_add_dialog (fwdzone, xml, xml.get_widget ('fwd_master_dialog'),TRUE)==gtk.RESPONSE_OK:
        fwdzone.set_dirty()
        model = tree_view.get_model ()
        iter = model.append ()
        model.set (iter,
                   COLUMN_PIXBUF, ns.get_pix (),
                   COLUMN_TEXT, ns.getHost(),
                   COLUMN_DATA, ns)
        tree_view.get_selection ().select_iter (iter)
    
def on_zone_ns_edit_button_clicked (*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('zone_ns_treeview')
    selected = tree_view.get_selection().get_selected ()
    if selected != None:
        (model, iter) = selected
        ns = model.get_value (iter, COLUMN_DATA)
        if ns.run_edit_dialog (fwdzone, xml, xml.get_widget ('fwd_master_dialog'),TRUE)==gtk.RESPONSE_OK:
            fwdzone.set_dirty()
            model.set (iter,
                       COLUMN_TEXT, ns.getHost(),
                       COLUMN_DATA, ns)
            tree_view.get_selection ().select_iter (iter)

def on_zone_ns_delete_button_clicked (clicked):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('zone_ns_treeview')
    result = tree_view.get_selection().get_selected ()
    if result != None:
        fwdzone.set_dirty()
        (model, iter) = result
        path = model.get_path (iter)
        ns = model.get_value (iter, COLUMN_DATA)
        
        if verify_delete(_("nameserver '%s'") % ns.getHost()) == gtk.RESPONSE_YES:
            model.remove (iter)
            try:
                iter = model.get_iter (path)
            except:
                pass
            if iter == None:
                path = (0)
            tree_view.get_selection().select_path (path)

def on_zone_mx_add_button_clicked (clicked):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('zone_mx_treeview')
    mx = FwdZone.MXProxy ()
    if mx.run_add_dialog (fwdzone, xml,xml.get_widget ('fwd_master_dialog'))==gtk.RESPONSE_OK:
        fwdzone.set_dirty()
        model = tree_view.get_model ()
        iter = model.append ()
        model.set (iter,
                   FwdZone.COLUMN_PIXBUF,mx.get_pix (),
                   FwdZone.COLUMN_MAIL_XCHANGE,mx.getHost(),
                   FwdZone.COLUMN_PRIORITY, str (mx.priority),
                   FwdZone.COLUMN_DATA,mx)
        tree_view.get_selection ().select_iter (iter)

def on_zone_mx_edit_button_clicked (*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('zone_mx_treeview')
    selected = tree_view.get_selection().get_selected ()
    if selected != None:
        (model, iter) = selected
        mx = model.get_value (iter, COLUMN_DATA)
        if mx.run_edit_dialog (fwdzone, xml,xml.get_widget ('fwd_master_dialog'))==gtk.RESPONSE_OK:
            fwdzone.set_dirty()
            model.set (iter,
                   FwdZone.COLUMN_PIXBUF,mx.get_pix (),
                   FwdZone.COLUMN_MAIL_XCHANGE,mx.getHost(),
                   FwdZone.COLUMN_PRIORITY, str (mx.priority),
                   FwdZone.COLUMN_DATA,mx)
            tree_view.get_selection ().select_iter (iter)

def on_zone_mx_delete_button_clicked (clicked):
    tree_view = xml.get_widget ('zone_mx_treeview')
    result = tree_view.get_selection().get_selected ()
    if result != None:
        (model, iter) = result
        path = model.get_path (iter)
        mx = model.get_value (iter, COLUMN_DATA)
        if verify_delete(_("mail exchanger '%s'") % mx.get_str()) == gtk.RESPONSE_YES:
            model.remove (iter)
            try:
                iter = model.get_iter (path)
            except:
                pass
            if iter == None:
                path = (0)
            tree_view.get_selection().select_path (path)


# FIXME add some GTK parameters here
def on_apply_activate():
    dialog = xml.get_widget ('bindconf')
    try:
        # Overall test
        try:
            broken_widget = None
            cfg.saveLocal()
        except TestError, message:
            generic_error_dialog (message.args, dialog, broken_widget=broken_widget)
            return
        update.set(FALSE)
        os.system("/sbin/service named reload &>/dev/null")
    except TestError, message:
        generic_error_dialog (message.args, dialog)
        return FALSE
# FIXME add some GTK parameters here
def on_apply_and_save_activate(*args):
    return on_apply_activate()

def on_generic_tree_view_selection_changed (selection, button1, button2,add_record_button,add_record_menu=None):
    response = selection.get_selected ()
    if response == None:
        button1.set_sensitive (FALSE)
        button2.set_sensitive (FALSE)
        button3.set_sensitive (FALSE)
    else:
        button1.set_sensitive (TRUE)
        button2.set_sensitive (TRUE)
        (model, iter) = response
        if iter!=None:
            zone = model.get_value (iter, COLUMN_DATA)
            if isinstance (zone, ConfNamed.ZoneFile) and zone.isSlave():
                add_record_button.set_sensitive (FALSE)
                if add_record_menu!= None:
                    add_record_menu.set_sensitive (FALSE)
            else:
                add_record_button.set_sensitive (TRUE)
                if add_record_menu != None:
                    add_record_menu.set_sensitive (TRUE)

def on_generic_tree_view_row_activated (tree_view, path, column, func):
    apply (func)

def on_generic_treeview_select_row (treeview, row, column, event, button1, button2):
    button1.set_sensitive (TRUE)
    button2.set_sensitive (TRUE)

def on_generic_treeview_unselect_row (treeview, row, column, event, button1, button2):
    button1.set_sensitive (FALSE)
    button2.set_sensitive (FALSE)

def on_generic_entry_insert_text (entry, partial_text, length, pos, str):
    text = partial_text[0:length]
    if re.match (str, text):
        return
    entry.emit_stop_by_name ('insert_text')

def on_new_activate (*args):
    on_bindconf_add_button_clicked (None)

def on_properties_activate (*args):
    on_bindconf_edit_button_clicked (None)

def on_delete_activate (*args):
    on_bindconf_delete_button_clicked (None)

def on_add_record_activate (*args):
    on_bindconf_add_record_button_clicked (None)

def on_exit_activate (*args):
    dialog = xml.get_widget("query_save_dialog")
    dialog.set_transient_for (xml.get_widget ('bindconf'))
    if update.get():
        status = dialog.run()
        if status == gtk.RESPONSE_APPLY:
            if on_apply_and_save_activate() == FALSE:
                dialog.hide()
                return FALSE
        elif status != gtk.RESPONSE_REJECT:
            dialog.hide()
            return FALSE
    gtk.mainquit()
    dialog.hide()
    return TRUE
def on_bindconf_delete_event(*args):
    return on_exit_activate(args)

def find_browser():
    try:
        path = '/usr/bin/mozilla'
        os.stat(path)
        return path
    except:
        try:
            path = '/usr/bin/galeon'
            os.stat(path)
            return path
        except:
            try:
                path = '/usr/bin/konqueror'
                os.stat(path)
                return path
            except:
                return None
            
#----------------------------------------------------------------------------
# Methods pertaining to the "Help" menu items, there will be more here
# once I have "real" help :)
#----------------------------------------------------------------------------
def on_manual_activate(args):
    page = "file:///usr/share/doc/redhat-config-bind-" + VERSION + "/index.html"
#    gnome.help_display_uri(page)
    gnome.url_show(page)

def on_about_activate (*args):
#    dialog = xml.get_widget("about")
    dialog = gnome.ui.About(PROGNAME,
                          VERSION,
                          '(C) 2002 Red Hat, Inc.',
                          FORMALNAME + "\n"+ _('Configures zone files'),
                          [ 'Jonathan Blanford <jrb@redhat.com>', 'Elliot Lee <sopwith@redhat.com>', 'Harald Hoyer <harald@redhat.com>','Daniel Walsh <dwalsh@redhat.com'],[ 'Tammy Fox <tfox@redhat.com>'],_("translator_credits"))
    dialog.set_title (FORMALNAME)
    dialog.set_transient_for (xml.get_widget ('bindconf'))
    dialog.show()

def reverse_ip_address (ip):
    foo = string.split(ip, '.')
    foo.reverse()
    return string.join(foo, '.')

def last_octet (ip):
    foo = ip.split('.')
    foo.reverse()
    return foo[0]

def get_subnet (ip):
    foo = ip.split('.')
    if len(foo) == 4:
        return "%s.%s.%s." % (foo[0],foo[1],foo[2])
    else:
        return ""


def ip_to_strhash (ip):
    if int (ip) < 10:
        return "00" + str (ip)
    if int (ip) < 100:
        return "0" + str (ip)
    return str (ip)

def on_rev_zone_changed(widget):
    zone = xml.get_widget ('rev_master_dialog').get_data ('zone')
    zone.this_dirty = TRUE

def on_rev_zone_name_entry_changed (entry):
    label = xml.get_widget ('rev_zone_reverse_label')
    text = reverse_ip_address (entry.get_text ())
    label.set_text (text + ".in-addr.arpa")
    on_rev_zone_changed(0)

def on_rev_zone_pns_changed (entry):
    text = entry.get_text ()
    on_rev_zone_changed(0)
    #FIXME: What's up with this????  Makes no sense.

def run_rev_zone_address_dialog (dialog, tree_view, parent, edit=FALSE):
    result = tree_view.get_selection().get_selected ()
    if result != None:
        (model, iter) = result
        if iter != None:
            selected_path = model.get_path (iter)
    else:
        model = tree_view.get_model ()
        iter = None
        selected_path = (0)
        if not edit:
            return None

    text = xml.get_widget ('rev_zone_name_entry').get_text ()
    xml.get_widget ('rev_master_address_label').set_text (add_dot (text))

    spin = xml.get_widget ('rev_master_address_spin')
    entry = xml.get_widget ('rev_master_address_entry')
    original=-1
    if edit:
        array = model.get_value (iter, COLUMN_DATA)
        original=int(array[0])
        spin.set_value (original)
        entry.set_text (array[1])
    else:
        spin.set_text ("")
        entry.set_text ("")
        ptr = None

    while 1:
        status = dialog.run ()
        if status != gtk.RESPONSE_OK:
            dialog.hide ()
            return status

        ip = spin.get_text ()
        host = entry.get_text ()
        if ip == "":
            generic_error_dialog (_("You must enter an octet."), dialog, broken_widget=spin)
            continue
        if host == "":
            generic_error_dialog (_("You must enter a hostname."), dialog, broken_widget=entry)
            continue

        try:
            host=add_dot(host)
            brw = entry
            Zone.testHost(host)
        except TestError, e:
            generic_error_dialog (e.args, dialog, broken_widget=brw)
            continue
        
        try:
            def check_foreach (model, path, iter, text):
                if edit and path == selected_path:
                    return FALSE
	        val = model.get_value (iter, COLUMN_DATA)
	        if isinstance (val, tuple):
		    if val[0] == ip: 
			raise 'Duplicate'
                return None
            if original != int(ip):
                model.foreach (check_foreach, add_dot (entry.get_text ()))
        except 'Duplicate':
            generic_error_dialog (_("A host with that octet already exists"), dialog, broken_widget=spin)
            continue
        dialog.hide ()
        break

    if edit:
	ptr=array[2]
	ptr.setIp(ip)
	ptr.setHost(host)
        model.set (iter,
                   COLUMN_TEXT, "%s%s->%s" % (add_dot (text),ip,host),
                   COLUMN_PARENT, parent,
                   COLUMN_DATA, (ip,host,ptr))
    else:
        if iter == None:
            iter = model.prepend ()
        else:
            iter = model.insert_before (iter)

        model.set (iter,
                   COLUMN_TEXT, "%s%s->%s" % (add_dot (text),ip,host),
                   COLUMN_PARENT, parent,
                   COLUMN_DATA, (ip,host,ptr))
    on_rev_zone_changed(0)
    tree_view.get_selection().select_iter (iter)
    update.set(TRUE)
    return status 


def on_rev_zone_add_button_clicked (*args):
    dialog = xml.get_widget ('rev_master_address_dialog')
    dialog.set_transient_for (xml.get_widget ('rev_master_dialog'))
    parent = xml.get_widget ('rev_master_dialog').get_data ('zone')
    dialog.set_title (_("Add Reverse Zone Pointer to %s") % parent.get_name())
    run_rev_zone_address_dialog (dialog,None,parent)

def on_rev_zone_edit_button_clicked (*args):
    dialog = xml.get_widget ('rev_master_address_dialog')
    dialog.set_title (_("Edit Reverse Zone Pointer"))
    dialog.set_transient_for (xml.get_widget ('rev_master_dialog'))
    parent = xml.get_widget ('rev_master_dialog').get_data ('zone')
    run_rev_zone_address_dialog (dialog, None, parent, TRUE)

def on_rev_zone_delete_button_clicked (button):
    tree_view = xml.get_widget ('rev_zone_treeview')
    result = tree_view.get_selection().get_selected ()
    if result != None:
        (model, iter) = result
        path = model.get_path (iter)
        rev = model.get_value (iter, COLUMN_DATA)
        if verify_delete(_("reverse address '%s'") % rev[1]) == gtk.RESPONSE_YES:
            model.remove (iter)
            try:
                iter = model.get_iter (path)
            except:
                pass
            if iter == None:
                path = (0)
            tree_view.get_selection().select_path (path)
            on_rev_zone_changed(0)

def on_rev_master_ns_add_button_clicked (button):
    tree_view = xml.get_widget ('rev_master_ns_treeview')
    selected = tree_view.get_selection().get_selected ()
    ns = FwdZone.NSProxy ()
    host_entry = xml.get_widget ('ns_host_entry')
    applies_to_entry = xml.get_widget ('ns_applies_to_entry')
    if ns.run_dialog (xml.get_widget ('rev_zone_reverse_label').get (), xml, FALSE, TRUE, xml.get_widget ('rev_master_dialog'), TRUE) == gtk.RESPONSE_OK:
        update.set(TRUE)
        model = tree_view.get_model ()
        iter = model.append ()
        model.set (iter,
                   COLUMN_PIXBUF, ns.get_pix (),
                   COLUMN_TEXT, ns.getHost(),
                   COLUMN_DATA, ns)
        tree_view.get_selection ().select_iter (iter)
        on_rev_zone_changed(0)

def on_rev_master_ns_edit_button_clicked (*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('rev_master_ns_treeview')
    selected = tree_view.get_selection().get_selected ()
    if selected != None:
        (model, iter) = selected
        ns = model.get_value (iter, COLUMN_DATA)
        host_entry = xml.get_widget ('ns_host_entry')
        applies_to_entry = xml.get_widget ('ns_applies_to_entry')
        if ns.run_dialog (xml.get_widget ('rev_zone_reverse_label').get (), xml, TRUE, TRUE, xml.get_widget ('fwd_master_dialog'), TRUE) == gtk.RESPONSE_OK:
            model.set (iter,
                       COLUMN_TEXT, ns.getHost())
            on_rev_zone_changed(0)


def on_rev_master_ns_delete_button_clicked (button):
    tree_view = xml.get_widget ('rev_master_ns_treeview')
    result = tree_view.get_selection().get_selected ()
    if result != None:
        (model, iter) = result
        path = model.get_path (iter)
        ns = model.get_value (iter, COLUMN_DATA)
        if verify_delete(_("nameserver '%s'") % ns.getHost()) == gtk.RESPONSE_YES:
            model.remove (iter)
            try:
                iter = model.get_iter (path)
            except:
                pass
            if iter == None:
                path = (0)
            tree_view.get_selection().select_path (path)
            on_rev_zone_changed(0)

def on_fwd_zone_set_button_clicked (button):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    dialog = xml.get_widget ('serial_dialog')
    dialog.set_transient_for (xml.get_widget ('fwd_master_dialog'))
    entry = xml.get_widget ('serial_entry')
    entry.grab_focus ()
    entry.set_text (str (fwdzone.serial))
    status = dialog.run ()
    dialog.hide ()

    if status != gtk.RESPONSE_OK: return status

    update.set(TRUE)

    serial = entry.get_text ()

    if serial == "": fwdzone.serial = 0
    else: fwdzone.serial = int (serial)

    fwdzone.dirty = TRUE
    fwdzone.zone.dirty = TRUE
    xml.get_widget ('fwd_zone_serial_entry').set_text (str (fwdzone.serial))
    return status

def on_rev_zone_set_button_clicked (button):
    zone = xml.get_widget ('rev_master_dialog').get_data ('zone')
    dialog = xml.get_widget ('serial_dialog')
    dialog.set_transient_for (xml.get_widget ('rev_master_dialog'))
    entry = xml.get_widget ('serial_entry')
    entry.grab_focus ()
    entry.set_text (str (zone.getSerial()))
    status = dialog.run ()
    dialog.hide ()

    if status != gtk.RESPONSE_OK: return status

    update.set(TRUE)

    serial = entry.get_text ()

    if serial == "": zone.serial = 0
    else: zone.serial = int (serial)

    zone.dirty = TRUE
    xml.get_widget ('rev_zone_serial_entry').set_text (str (zone.serial))
    return status

def on_rev_zone_soa_button_clicked (button):
    zone = xml.get_widget ('rev_master_dialog').get_data ('zone')
    soa = zone.getSOA()
    xml.get_widget ('soa_refresh_entry').set_text (str (soa.getRefresh()))
    xml.get_widget ('soa_retry_entry').set_text (str (soa.getRetry()))
    xml.get_widget ('soa_expire_entry').set_text (str (soa.getExpire()))
    xml.get_widget ('soa_minimum_entry').set_text (str (soa.getTTL()))
    dialog = xml.get_widget ('soa_dialog')
    dialog.set_transient_for (xml.get_widget ('fwd_master_dialog'))

    status = dialog.run ()
    dialog.hide ()
    if status != gtk.RESPONSE_OK:
        return status

    def my_int (str):
        try:
            i = int (str)
            return i
        except:
            return 0
    soa.setRefresh(my_int (xml.get_widget ('soa_refresh_entry').get_text ()))
    soa.setRetry(my_int (xml.get_widget ('soa_retry_entry').get_text ()))
    soa.setExpire(my_int (xml.get_widget ('soa_expire_entry').get_text ()))
    soa.setTTL(my_int (xml.get_widget ('soa_minimum_entry').get_text ()))
    return status

def on_fwd_zone_soa_button_clicked (button):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    fwdzone.hydrate_soa ()
    dialog = xml.get_widget ('soa_dialog')
    dialog.set_transient_for (xml.get_widget ('fwd_master_dialog'))
    status = dialog.run ()
    dialog.hide ()
    if status == gtk.RESPONSE_OK:
        fwdzone.dehydrate_soa ()
        fwdzone.set_dirty()
    return status

def on_fwd_zone_name_entry_changed (*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    fwdzone.set_name (xml.get_widget ('fwd_zone_name_entry').get_text ())

def on_fwd_zone_treeview_select_row (selection):
    result = selection.get_selected ()
    if result == None:
        xml.get_widget ('fwd_zone_delete_button').set_sensitive (FALSE)
        xml.get_widget ('fwd_zone_edit_button').set_sensitive (FALSE)
    else:
        xml.get_widget ('fwd_zone_delete_button').set_sensitive (TRUE)
        xml.get_widget ('fwd_zone_edit_button').set_sensitive (TRUE)

def on_rr_toggled (toggle):
    label1 = xml.get_widget ('rr_label1')
    label2 = xml.get_widget ('rr_label2')

    if xml.get_widget ('rr_address_rbutton').get_active ():
        label1.set_text (_("Host or Domain Name:"))
        label2.set_text (_("Served By:"))
    elif xml.get_widget ('rr_address_rbutton').get_active ():
        label1.set_text (_("Alias:"))
        label2.set_text (_("Host Name:"))
    else:
        label1.set_text (_("Host Name:"))
        label2.set_text (_("Resolves To:"))

def on_rr_type_menu_selection_done (menu, *args):
    i = menu.get_children().index(menu.get_active())

    xml.get_widget ('rr_type_notebook').set_current_page (i)

def add_fwd_zone (parent,fwdzone):
    global    fwd_zone_first_time
    dialog = xml.get_widget ('rr_type_dialog')
    dialog.set_transient_for (parent)
    dialog.set_title (_("Add Record to %s") % fwdzone.name)

    notebook = xml.get_widget ('rr_type_notebook')
    add_reverse_check=xml.get_widget ('rr_add_reverse_checkbutton')

    if fwd_zone_first_time:
        notebook.set_current_page (0)
        add_reverse_check.set_active(gtk.TRUE)
        fwd_zone_first_time=gtk.FALSE

    xml.get_widget ('rr_host_label').set_text ("." + fwdzone.name)
    xml.get_widget ('rr_alias_label').set_text ("." + fwdzone.name)
    xml.get_widget ('rr_nameserver_label').set_text ("." + fwdzone.name)
    xml.get_widget ('rr_host_host_entry').set_text ('')
    prev_add=xml.get_widget ('rr_host_address_entry').get_text ()
    xml.get_widget ('rr_host_address_entry').set_text (get_subnet(prev_add))
    xml.get_widget ('rr_alias_alias_entry').set_text ('')
    xml.get_widget ('rr_nameserver_host_entry').set_text ('')
    xml.get_widget ('rr_nameserver_handled_entry').set_text ('')
    xml.get_widget ('rr_mx_host_entry').set_text ('')
    rev_tree_view=xml.get_widget ('rr_add_reverse_treeview')

    mx_tree_view=xml.get_widget ('rr_mx_treeview')
    rev_model = rev_tree_view.get_model()
    sel_path = (0,)
    result = rev_tree_view.get_selection().get_selected ()
    if result != None:
        (model, iter) = result
	if iter != None:
            sel_path = model.get_path (iter)
    rev_model.clear ()

    cname_tree_view=xml.get_widget ('rr_cname_treeview')
    cname_model = cname_tree_view.get_model()
    cname_model.clear()
    mx_tree_view=xml.get_widget ('rr_mx_treeview')
    mx_model = mx_tree_view.get_model()
    mx_model.clear()

    zlist = fwdzone.zone.getAList()
    for zone in zlist:
        name=zone.getName()+ "." + fwdzone.name +"."
        iter = mx_model.append()
        mx_model.set (iter,
                       COLUMN_PIXBUF, FwdZone.image_a,
                       COLUMN_TEXT, name)
        iter = cname_model.append()
        cname_model.set (iter,
                       COLUMN_PIXBUF, FwdZone.image_a,
                       COLUMN_TEXT, name)

    zlist = cfg.getReverseZoneList()
    for zone in zlist:
        iter = rev_model.append()
        rev_model.set (iter,
                       COLUMN_PIXBUF, image_reverse,
                       COLUMN_TEXT, zone.getName(),
                       COLUMN_DATA, zone)
    rev_tree_view.get_selection().select_path (sel_path)
            
    while 1:
        status = dialog.run ()
        if status != gtk.RESPONSE_OK:
            dialog.hide ()
            return status
        i = notebook.get_current_page()
        update.set(TRUE)
        try:
            if i == 0:
                broken_widget = xml.get_widget ('rr_host_host_entry')
                host = broken_widget.get_text ()
                Zone.testHost(host)
                broken_widget = xml.get_widget ('rr_host_address_entry')
                ip = broken_widget.get_text ()
                Zone.testIp(ip)
                fwdzone.zone.zone.addA(host,[ip])
                if add_reverse_check.get_active():
                    result = rev_tree_view.get_selection().get_selected ()
                    if result != None:
                        (rev_model, rev_iter) = result
                        if rev_iter != None:
                            rev_zone = rev_model.get_value (rev_iter, COLUMN_DATA)
                            rev_zone.zone.addPTR(add_dot(host)+ fwdzone.name + ".",last_octet (ip))
                            rev_zone.this_dirty=TRUE
                            rev_zone.zone.incSerial()
                            bindconf_model= xml.get_widget ('bindconf_treeview').get_model()

                            def set_foreach (model, path, iter, data):
                                zone = model.get_value (iter, COLUMN_DATA)
                                if isinstance (zone, ConfNamed.ZoneFile):
                                    if zone.isReverse() and zone.getName() == data:
                                        loadReverseZone(model,iter,rev_zone)
                                        return TRUE
                                return FALSE

                            bindconf_model.foreach (set_foreach, rev_zone.getName())

            elif i == 1:
                broken_widget = xml.get_widget ('rr_alias_alias_entry')
                alias = broken_widget.get_text ()
                Zone.testHost(alias)
                cname_tree_view=xml.get_widget ('rr_cname_treeview')
                (model, iter) = cname_tree_view.get_selection().get_selected ()
                if model == None or iter == None:
                    raise TestError, _("You must select a Host Name.") 
                else:
                    host = model.get_value (iter, COLUMN_TEXT)
                #FIXE: check this value
                fwdzone.zone.zone.addCNAME([host,alias])
            elif i == 2:
                broken_widget = xml.get_widget ('rr_nameserver_host_entry')
                host = broken_widget.get_text ()
                Zone.testHost(host)
                broken_widget = xml.get_widget ('rr_nameserver_handled_entry')
                applies_to = broken_widget.get_text ()
                Zone.testAppliesTo(applies_to)
                #FIXME: check this value
                fwdzone.zone.zone.addNS(host,applies_to)
            elif i == 3:
                broken_widget = xml.get_widget ('rr_mx_host_entry')
                name = broken_widget.get_text ()
                Zone.testHost(name)
                broken_widget = xml.get_widget ('rr_mx_priority')
                priority = broken_widget.get_text ()
                mx_tree_view=xml.get_widget ('rr_mx_treeview')
                (model, iter) = mx_tree_view.get_selection().get_selected ()
                if model == None or iter == None:
                    raise TestError, _("You must select a Mail Server.") 
                else:
                    server = model.get_value (iter, COLUMN_TEXT)
                #FIXME: check this value
                fwdzone.zone.zone.addMX([priority,server],name)
        except TestError, message:
            generic_error_dialog (message.args, dialog, broken_widget=broken_widget)
            continue
        break


    fwdzone.dirty = TRUE
    dialog.hide ()
    return status


def on_fwd_zone_add_button_clicked (button):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    add_fwd_zone (xml.get_widget ('fwd_master_dialog'),fwdzone)


def on_fwd_zone_edit_button_clicked (*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('fwd_zone_treeview')
    (model, iter) = tree_view.get_selection().get_selected ()
    zone = model.get_value (iter, COLUMN_DATA)
    if zone.run_edit_dialog (fwdzone, xml,xml.get_widget ('fwd_master_dialog')) == gtk.RESPONSE_OK:
        update.set(TRUE)
        model.set (iter,
                   COLUMN_TEXT, '',
                   COLUMN_TEXT, zone.get_str(),
                   )

def on_fwd_zone_delete_button_clicked (button):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    tree_view = xml.get_widget ('fwd_zone_treeview')
    (model, iter) = tree_view.get_selection().get_selected ()

    data = model.get_value (iter, COLUMN_DATA)
    parent = model.get_value (iter, COLUMN_PARENT)
    if verify_delete(data.get_str()) == gtk.RESPONSE_YES:
        if isinstance (data, FwdZone.AProxy):
            fwdzone.a.remove (data)
        elif isinstance (data, FwdZone.CNAMEProxy):
            fwdzone.cname.remove (data)
        elif isinstance (data, FwdZone.NSProxy):
            fwdzone.ns.remove (data)
        path = model.get_path (iter)
        model.remove (iter)
        tree_view.get_selection().select_path (path)
        update.set(TRUE)

def zone_changed(*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    if fwdzone:
        on_fwd_zone_changed(0)
    else:
        on_rev_zone_changed(0)

def on_fwd_zone_changed (*args):
    fwdzone = xml.get_widget ('fwd_master_dialog').get_data ('fwdzone')
    fwdzone.set_dirty ()

def on_mx_button_toggled (toggle):
    active = xml.get_widget ('mx_other_rbutton').get_active ()
    xml.get_widget ('mx_applies_to_entry').set_sensitive (active)

###
### Edit zones
###

def on_edit_forward_zone (zone):
    dialog = xml.get_widget ('fwd_master_dialog')
    dialog.set_transient_for (xml.get_widget ('bindconf'))
    fwdzone = FwdZone.FwdZone (zone, xml)
    dialog.set_data ('fwdzone', fwdzone)
    fwdzone.hydrate ()
    while 1:
        status = dialog.run ()
        if status != gtk.RESPONSE_OK:
            dialog.hide ()
            dialog.set_data ('fwdzone', None)
            return status

        try:
            fwdzone.check ()
        except TestError, e:
            generic_error_dialog (e.args, dialog)
            continue
        break

    update.set(TRUE)
    dialog.set_data ('fwdzone', None)
    dialog.hide ()
    fwdzone.dehydrate ()
    return status

def getZoneSubnet(zone):
    match = re.match (r'(.*).in-addr.arpa', zone.getName ())
    if match:
        return reverse_ip_address (match.group (1))
    else:
        return ""

def on_edit_reverse_zone (zone):
    zone.dirty = FALSE
    zone.this_dirty = TRUE # bad hack
    dialog = xml.get_widget ('rev_master_dialog')
    dialog.set_transient_for (xml.get_widget ('bindconf'))
    dialog.set_data('zone', zone)
    zone_entry = xml.get_widget ('rev_zone_name_entry')
    contact_entry = xml.get_widget ('rev_zone_contact_entry')
    serial_entry = xml.get_widget ('rev_zone_serial_entry')
    file_entry = xml.get_widget ('rev_zone_file_entry')
    pns_entry = xml.get_widget('rev_zone_pns_entry')
    tree_view = xml.get_widget ('rev_zone_treeview')
    ns_tree_view = xml.get_widget ('rev_master_ns_treeview')
    xml.get_widget ('rev_master_ok_button').grab_default ()
    zone_entry.grab_focus ()
    text=getZoneSubnet(zone)
    zone_entry.set_text (text)
    file_entry.set_text (zone.getFile ())
    contact_entry.set_text (zone.getSOA().getContact ())
    serial_entry.set_text (str(zone.getSOA().getSerial ()))
    pns_entry.set_text (zone.getSOA().getPNS())

    zone.this_dirty = FALSE # Bad hack, part deux
    while 1:
        status = dialog.run ()
        if status != gtk.RESPONSE_OK:
            dialog.hide ()
            return status

        text = zone_entry.get_text ()
        #FIXME4: fix wording
        if text == "" or not re.match (r'^\d+\.\d+\.\d+$', text):
            generic_error_dialog (_("You must have a valid IP domain."), dialog, broken_widget=zone_entry)
            continue

        # tests
        try:
            broken_widget = zone_entry
            text = reverse_ip_address (text)
            zone.testName (text + '.in-addr.arpa')
            
            broken_widget = pns_entry
            zone.getSOA().testPNS(pns_entry.get_text())

            broken_widget = file_entry
            zone.testFile(file_entry.get_text())
            
        except TestError, message:
            generic_error_dialog (message.args, dialog, broken_widget=broken_widget)
            continue


        if zone.this_dirty and not zone.dirty:
            serial = int(serial_entry.get_text()) + 1
            serial_entry.set_text(str(serial))
            
        zone.setFile(file_entry.get_text())
        zone.setName (text + '.in-addr.arpa')
        soa=zone.getSOA()
        soa.setContact(contact_entry.get_text())
        soa.setSerial(int(serial_entry.get_text()))
        soa.setPNS(pns_entry.get_text())

        # all tests passed and all values are set
        break
    update.set(TRUE)
    dialog.hide ()
    return status

def on_slave_zone_masters_add_button_clicked(button):
    masters_widget = xml.get_widget ('slave_zone_masters_entry')
    masters_treeview = xml.get_widget ('slave_zone_masters_treeview')
    model=masters_treeview.get_model()
    ip=masters_widget.get_text() 
    if Zone.checkIpNum(ip):
        iter = model.append()
        model.set (iter,
                   COLUMN_TEXT, ip)
        masters_widget.set_text("")

def on_slave_zone_masters_delete_button_clicked(button):
    tree_view = xml.get_widget ('slave_zone_masters_treeview')
    result = tree_view.get_selection().get_selected()
    if result == None:
        return
    (model, iter) = result
    if iter != None:
        ip = model.get_value (iter, COLUMN_TEXT)
        if verify_delete(_("master '%s'") % ip) == gtk.RESPONSE_YES:
            model.remove (iter)

def on_edit_slave_zone (zone):
    dialog = xml.get_widget ('slave_zone_dialog')
    dialog.set_transient_for (xml.get_widget ('bindconf'))
    name_widget = xml.get_widget ('slave_zone_name_entry')
    masters_widget = xml.get_widget ('slave_zone_masters_entry')
    masters_treeview = xml.get_widget ('slave_zone_masters_treeview')
    model=masters_treeview.get_model()
    model.clear()
    
    file_widget = xml.get_widget ('slave_zone_file_entry')

    masters = zone.getMasters ()
    for i in masters:
        iter = model.append()
        model.set (iter,
                   COLUMN_TEXT, i)

    name_widget.set_text (zone.getName ())
    file_widget.set_text (zone.getFile ())

    while 1:
        status = dialog.run ()
        dialog.hide ()
        if status != gtk.RESPONSE_OK:
            return status

        name_str = name_widget.get_text ()
        masters_list=[]
        def foreach_func (model, path, iter, text):
            ip = model.get_value (iter, COLUMN_TEXT)
            masters_list.append(ip)
            return FALSE
        
        model.foreach (foreach_func, "")
        file_str = file_widget.get_text ()

        try:
            broken_widget = name_widget
            zone.testName (name_str)
            broken_widget = file_str
            zone.testFile (file_str)            
        except TestError, message:
            generic_error_dialog (message.args, dialog, broken_widget=broken_widget)
            continue
            

        zone.setName (name_str)
        zone.setFile (file_str)
        masters = ConfNamed.Servers (["masters"])
        for ip in masters_list:
            masters.setOpt (ip, ";")
        zone.setServers(masters)
        try:
            zone.test()
        except TestError, message:
            generic_error_dialog (message.args, dialog)
            continue
            
        break
    update.set(TRUE)
    return status
    
def on_zone_type_toggled (button):
    notebook = xml.get_widget ('zone_type_notebook')
    if xml.get_widget ('fwd_zone_rbutton').get_active ():
        notebook.set_current_page (0)
    elif xml.get_widget ('rev_zone_rbutton').get_active ():
        notebook.set_current_page (1)
    else:
        notebook.set_current_page (2)
    xml.get_widget ('zone_type_entry').set_text ("")

def on_bindconf_add_button_clicked (button):
    tree_view = xml.get_widget ('bindconf_treeview')
    dialog = xml.get_widget ('zone_type_dialog')
    dialog.set_transient_for (xml.get_widget ('bindconf'))
    # bit of a hack, but we do this to avoid setting the size
    # on the widget
    xml.get_widget ('fwd_zone_rbutton').set_active (TRUE)
    xml.get_widget ('rev_zone_rbutton').set_active (TRUE)
    xml.get_widget ('slave_zone_rbutton').set_active (TRUE)
    xml.get_widget ('fwd_zone_rbutton').set_active (TRUE)
    xml.get_widget ('zone_type_entry').grab_focus ()
    result = tree_view.get_selection().get_selected ()
    if result == None:
        model = tree_view.get_model ()
        iter = None
    else:
        (model, iter) = result

    while 1:
        status = dialog.run ()

        if status != gtk.RESPONSE_OK:
            dialog.hide ()
            return
        name = xml.get_widget ('zone_type_entry').get_text ()

        if xml.get_widget ('fwd_zone_rbutton').get_active ():
            file = name + ".zone"

            try:
                brw = xml.get_widget ('zone_type_entry')
                Zone.testName(name)
                Zone.testFile(file)
            except TestError, e:
                generic_error_dialog (e.args, dialog, broken_widget=brw)
                continue
            
            zone = cfg.addZone (name,file)
            iter = model.append(None)
            model.set (iter,
                       COLUMN_PIXBUF, image_domain,
                       COLUMN_TEXT, name,
                       COLUMN_DATA, zone)
        elif xml.get_widget ('rev_zone_rbutton').get_active ():
            name = reverse_ip_address (name) + ".in-addr.arpa"
            file = name + ".zone"
            try:
                brw = xml.get_widget ('zone_type_entry')
                Zone.testName(name)
                Zone.testFile(file)
            except TestError, e:
                generic_error_dialog (e.args, dialog, broken_widget=brw)
                continue
            
            zone = cfg.addZone (name,file,"master")
            iter = model.append(None)
            model.set (iter,
                       COLUMN_PIXBUF, image_reverse,
                       COLUMN_TEXT, name,
                       COLUMN_DATA, zone)
        else:
            file = name + ".zone"

            try:
                brw = xml.get_widget ('zone_type_entry')
                Zone.testName(name)
                Zone.testFile(file)
            except TestError, e:
                generic_error_dialog (e.args, dialog, broken_widget=brw)
                continue
            
            zone = cfg.addZone (name,name + ".zone","slave")
            iter = model.append(None)
            model.set (iter,
                       COLUMN_PIXBUF, image_slave,
                       COLUMN_TEXT, name,
                       COLUMN_DATA, zone)
        break
    dialog.hide ()
    tree_view.get_selection ().select_iter (iter)
    if on_bindconf_edit_button_clicked() != gtk.RESPONSE_OK:
        return deleteCurrentRecord(FALSE)

def on_bindconf_add_record_button_clicked (button):
    status = gtk.RESPONSE_CANCEL
    tree_view = xml.get_widget ('bindconf_treeview')
    result = tree_view.get_selection().get_selected()
    if result == None:
        return status
    (model, iter) = result
    zone = model.get_value (iter, COLUMN_DATA)
    try:
        parentZone = model.get_value (iter, COLUMN_PARENT)
        if (parentZone != None):
            zone=parentZone
            parent = model.iter_parent(iter)
        else:
            parent=iter
            
    except:
        pass
    if isinstance (zone, ConfNamed.ZoneFile):
        if zone.isReverse():
            dialog = xml.get_widget ('rev_master_address_dialog')
            dialog.set_title (_("Add Record to %s") % zone.zone.getName())
            dialog.set_transient_for (xml.get_widget ('bindconf'))
            status=add_rev_zone_address_dialog (dialog,zone)
            if status != gtk.RESPONSE_OK:
                return status
            loadReverseZone(model,parent,zone)
        else:
            fwdzone = FwdZone.FwdZone (zone, xml)
            dialog = xml.get_widget ('fwd_master_dialog')
            dialog.set_data ('fwdzone', fwdzone)
            fwdzone.hydrate ()
            status=add_fwd_zone (xml.get_widget ('bindconf'),fwdzone)
            if status != gtk.RESPONSE_OK:
                return status
            try:
                fwdzone.check ()
                fwdzone.dehydrate ()
            except TestError, e:
                generic_error_dialog (e.args, dialog)
            loadForwardZone(model,parent,zone)
        path=model.get_path (parent)
        tree_view.expand_row(path,0)
        tree_view.get_selection().select_path (path)
        
    else: #Unrecognized zone.
	print "unrecognized",zone,type(zone),dir(zone)
        return status

    zone.incSerial()

def on_bindconf_edit_button_clicked (*args):
    status = gtk.RESPONSE_CANCEL
    tree_view = xml.get_widget ('bindconf_treeview')
    result = tree_view.get_selection().get_selected()
    if result == None:
        return status
    
    (model, iter) = result
    zone = model.get_value (iter, COLUMN_DATA)
    if isinstance (zone, ConfNamed.ZoneFile):
        if zone.isReverse():
            status=on_edit_reverse_zone (zone)
            if status != gtk.RESPONSE_OK:
                return status
            loadReverseZone(model,iter,zone)
            tree_view.expand_row(model.get_path (iter),0)
            pix = image_reverse
        elif zone.isSlave():
            status=on_edit_slave_zone (zone)
            if status != gtk.RESPONSE_OK:
                return status
            pix = image_slave
        else:
            status=on_edit_forward_zone (zone)
            if status != gtk.RESPONSE_OK:
                return status
            pix = image_domain
            loadForwardZone(model,iter,zone)
            tree_view.expand_row(model.get_path (iter),0)
    elif isinstance (zone, Zone.A):
        parent = model.get_value (iter, COLUMN_PARENT)
        if (parent != None):
            fwdzone = FwdZone.FwdZone (parent, xml)
            proxy = FwdZone.AProxy (zone)
	    status = proxy.run_edit_dialog (fwdzone, xml,xml.get_widget ('bindconf'))
            if status != gtk.RESPONSE_OK:
                return status

	    zone.setIp(proxy.ip)
	    zone.setHost(proxy.host)
            model.set (iter,
                       COLUMN_PIXBUF, proxy.get_pix (),
                       COLUMN_TEXT, proxy.get_str(),
                       COLUMN_PARENT, parent,
                       COLUMN_DATA, zone
                       )
            update.set(TRUE)
            parent.getSOA().setSerial(parent.getSOA().getSerial()+1)
            
        return status
    elif isinstance (zone, Zone.CNAME):
        parent = model.get_value (iter, COLUMN_PARENT)
        if (parent != None):
            fwdzone = FwdZone.FwdZone (parent, xml)
            proxy = fwdzone.getCNAMEProxy (zone.getAlias())
            status = proxy.run_edit_dialog (fwdzone, xml,xml.get_widget ('bindconf'))
            if status == gtk.RESPONSE_OK:
                zone.setAlias(proxy.alias)
                zone.setHost(proxy.host)
                model.set (iter,
                           COLUMN_PIXBUF, proxy.get_pix (),
                           COLUMN_TEXT, proxy.get_str(),
                           COLUMN_DATA, zone,
                           COLUMN_PARENT, parent)
                update.set(TRUE)
                parent.getSOA().setSerial(parent.getSOA().getSerial()+1)
        return status
    elif isinstance (zone, Zone.MX):
        parent = model.get_value (iter, COLUMN_PARENT)
        if (parent != None):
            fwdzone = FwdZone.FwdZone (parent, xml)
            proxy = fwdzone.getMXProxy (zone.getName())
            status = proxy.run_edit_dialog (fwdzone, xml,xml.get_widget ('bindconf'))
            if status == gtk.RESPONSE_OK:
                zone.setName(proxy.name)
                zone.setServer(proxy.server)
                zone.setPriority(proxy.priority)
                model.set (iter,
                           COLUMN_PIXBUF, proxy.get_pix (),
                           COLUMN_TEXT, proxy.get_str(),
                           COLUMN_DATA, zone,
                           COLUMN_PARENT, parent)
                update.set(TRUE)
                parent.getSOA().setSerial(parent.getSOA().getSerial()+1)
        return status
    elif isinstance (zone, Zone.NS):
        parent = model.get_value (iter, COLUMN_PARENT)
        if (parent != None):
            fwdzone = FwdZone.FwdZone (parent, xml)
            proxy = FwdZone.NSProxy (zone)
            status = proxy.run_edit_dialog (fwdzone, xml,xml.get_widget ('bindconf'))
            if status == gtk.RESPONSE_OK:
                zone.setHost(proxy.host)
                zone.setAppliesTo(proxy.applies_to)
                model.set (iter,
                           COLUMN_PIXBUF, proxy.get_pix (),
                           COLUMN_TEXT, proxy.get_str(),
                           COLUMN_DATA, zone,
                           COLUMN_PARENT, parent)
                update.set(TRUE)
                parent.getSOA().setSerial(parent.getSOA().getSerial()+1)
        return status
    elif isinstance (zone, tuple):
        parent = model.get_value (iter, COLUMN_PARENT)
        dialog = xml.get_widget ('rev_master_address_dialog')
        dialog.set_title (_("Edit Reverse Zone Pointer"))
	master=xml.get_widget ('rev_master_dialog')
	ptr=zone[2]
	master.set_data('zone', ptr)
	dialog.set_transient_for (xml.get_widget ('bindconf'))
        xml.get_widget ('rev_zone_name_entry').set_text (getZoneSubnet(parent))
        tree_view = xml.get_widget ('bindconf_treeview')
        status = run_rev_zone_address_dialog (dialog, tree_view,parent, TRUE)
        if status == gtk.RESPONSE_OK:
            parent.getSOA().setSerial(parent.getSOA().getSerial()+1)
        return status
    else: #Unrecognized zone.
        print "edit unrecognized",zone,type(zone),dir(zone)
        return status

    name = zone.getName ()
    model.set (iter,
               COLUMN_PIXBUF, pix,
               COLUMN_TEXT, name)
    return status

def deleteCurrentRecord(prompt=TRUE):
    tree_view = xml.get_widget ('bindconf_treeview')
    result = tree_view.get_selection().get_selected()
    if result == None:
        return
    (model, iter) = result
    data = model.get_value (iter, COLUMN_DATA)
    if isinstance (data, tuple):
        if prompt and verify_delete(data[2].getName()) == gtk.RESPONSE_NO:
            return
        data[2].unlink()
    else:
        if prompt and verify_delete(data.getName()) == gtk.RESPONSE_NO:
            return
        data.unlink ()
    
    zone = model.get_value (iter, COLUMN_PARENT)
    if zone != None:
        zone.getSOA().setSerial(zone.getSOA().getSerial()+1)

    path = model.get_path (iter)
    model.remove (iter)
    tree_view.get_selection ().select_path (path)
    result = tree_view.get_selection().get_selected()
    if result == None or result[1] == None:
        tree_view.get_selection().select_path ((0,))

def on_bindconf_delete_button_clicked (button):
    deleteCurrentRecord()
    update.set(TRUE)
    
def loadReverseZone(model,parent,zone):
    name = zone.getName ()
    model.set (parent,
               COLUMN_PIXBUF, image_reverse,
               COLUMN_TEXT, name,
               COLUMN_DATA, zone)
            
    total=model.iter_n_children(parent)
    for i in xrange(0,total):
        child = model.iter_nth_child(parent,total-i-1 )
        model.remove(child)

    text=getZoneSubnet(zone)
    nslist = zone.getNSList ()
    for ns in nslist:
        proxy = FwdZone.NSProxy (ns)
#        if proxy.applies_to == '@':
#            continue
        iter = model.append (parent)
        model.set (iter,
                   COLUMN_PIXBUF, proxy.get_pix (),
                   COLUMN_TEXT, proxy.get_str(),
                   COLUMN_DATA, ns,
                   COLUMN_PARENT, zone)

    ptrlist = zone.getPTRList ()
    for ptr in ptrlist:
        ip = str(ptr.getIp ())
        host = ptr.getHost ()
        iter = model.append (parent)
        if len (text) > 1 and text[-1] != '.':
            realip = text + '.' + ip
        else:
            realip = text + ip
        model.set (iter,
                   COLUMN_PIXBUF, image_reverse,
                   COLUMN_TEXT, realip+"->"+host,
                   COLUMN_DATA, (ip,host,ptr),
                   COLUMN_PARENT, zone)
            
    nslist = zone.getNSList ()
    for ns in nslist:
        proxy = FwdZone.NSProxy (ns)
        if proxy.applies_to == '@':
            continue
        iter = model.append (parent)
        model.set (iter,
                   COLUMN_PIXBUF, proxy.get_pix (),
                   COLUMN_TEXT, proxy.get_str(),
                   COLUMN_DATA, ns,
                   COLUMN_PARENT, zone)

def loadForwardZone(model,parent,zone):
    name = zone.getName()
    model.set (parent,
               COLUMN_PIXBUF, image_domain,
               COLUMN_TEXT, name,
               COLUMN_DATA, zone)
    total=model.iter_n_children(parent)
    for i in xrange(0,total):
        child=model.iter_nth_child(parent,total-i-1 )
        model.remove(child)

    nslist = zone.getNSList ()
    for ns in nslist:
        proxy = FwdZone.NSProxy (ns)
#        if proxy.applies_to == '@':
#            continue
        iter = model.append (parent)
        model.set (iter,
                   COLUMN_PIXBUF, proxy.get_pix (),
                   COLUMN_TEXT, proxy.get_str(),
                   COLUMN_DATA, ns,
                   COLUMN_PARENT, zone)

    alist = zone.getAList ()
    for a in alist:
        proxy = FwdZone.AProxy (a)
        if proxy.host == '@':
            continue
        iter = model.append (parent)
        model.set (iter,
                   COLUMN_PIXBUF, FwdZone.image_a,
                   COLUMN_TEXT, proxy.get_str(),
                   COLUMN_DATA, a,
                   COLUMN_PARENT, zone)
                    
    cnamelist = zone.getCNAMEList ()
    for cname in cnamelist:
        proxy = FwdZone.CNAMEProxy (cname)
        if proxy.host == '@':
            continue
        iter = model.append (parent)
        model.set (iter,
                   COLUMN_PIXBUF, proxy.get_pix (),
                   COLUMN_TEXT, proxy.get_str(),
                   COLUMN_DATA, cname,
                   COLUMN_PARENT, zone)

    mxlist = zone.getMXList ()
    for mx in mxlist:
        proxy = FwdZone.MXProxy (mx)
        iter = model.append (parent)
        model.set (iter,
                   COLUMN_PIXBUF, proxy.get_pix (),
                   COLUMN_TEXT, proxy.get_str(),
                   COLUMN_DATA, mx,
                   COLUMN_PARENT, zone)

def setup_main_tree ():
    tree_view = xml.get_widget ('bindconf_treeview')
    model = MyTreeModel()
    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererPixbuf(), pixbuf=COLUMN_PIXBUF)
    tree_view.append_column (column)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText(), text=COLUMN_TEXT)
    tree_view.append_column (column)
    tree_view.get_selection().connect ("changed",
                                       on_generic_tree_view_selection_changed,
                                       xml.get_widget ('bindconf_edit_button'), xml.get_widget ('bindconf_delete_button'),xml.get_widget ('bindconf_add_record_button'),xml.get_widget('add_record_menu'))
    tree_view.connect ("row_activated",
                       on_generic_tree_view_row_activated, on_bindconf_edit_button_clicked)

    zlist = cfg.getSlaveZoneList()
    for zone in zlist:
        name = zone.getName ()
        iter = model.append (None)
        model.set (iter,
                   COLUMN_PIXBUF, image_slave,
                   COLUMN_TEXT, name,
                   COLUMN_DATA, zone)

    zlist = cfg.getForwardZoneList()
    for zone in zlist:
        parent = model.append (None)
        loadForwardZone(model,parent,zone)
        
    zlist = cfg.getReverseZoneList()
    for zone in zlist:
        parent = model.append (None)
        loadReverseZone(model,parent,zone)
            
    tree_view.get_selection().select_path ((0,))
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)

def setup_cname_treeview():
    tree_view = xml.get_widget ('cname_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING)
    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererPixbuf(), pixbuf=COLUMN_PIXBUF)
    tree_view.append_column (column)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText(), text=COLUMN_TEXT)
    tree_view.append_column (column)
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)
    
def setup_mx_treeview():
    tree_view = xml.get_widget ('mx_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING)
    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererPixbuf(), pixbuf=COLUMN_PIXBUF)
    tree_view.append_column (column)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText(), text=COLUMN_TEXT)
    tree_view.append_column (column)
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)

def setup_zone_mx_treeview():
    tree_view = xml.get_widget ('zone_mx_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,gobject.TYPE_STRING,gobject.TYPE_STRING)

    tree_view.set_model (model)
    column = gtk.TreeViewColumn (_("Mail Exchanger"), gtk.CellRendererText (), text=FwdZone.COLUMN_MAIL_XCHANGE)
    column.set_sizing (gtk.TREE_VIEW_COLUMN_AUTOSIZE)
    tree_view.append_column (column)

    column = gtk.TreeViewColumn (_("Priority"), gtk.CellRendererText (), text=FwdZone.COLUMN_PRIORITY)
    column.set_sizing (gtk.TREE_VIEW_COLUMN_AUTOSIZE)
    tree_view.append_column (column)

    model.set_sort_column_id (FwdZone.COLUMN_PRIORITY, gtk.SORT_ASCENDING)
    model.set_sort_func(FwdZone.COLUMN_PRIORITY,on_sort)
    tree_view.get_selection().connect ("changed",
                                       on_generic_tree_view_selection_changed,
                                       xml.get_widget ('zone_mx_edit_button'), xml.get_widget ('zone_mx_delete_button'),xml.get_widget ('bindconf_add_record_button'))
    tree_view.connect ("row_activated",
                       on_generic_tree_view_row_activated, on_zone_mx_edit_button_clicked)
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)

def setup_slave_zone_treeview():
    tree_view = xml.get_widget ('slave_zone_masters_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)

    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText (), text=COLUMN_TEXT)
    column.set_sizing (gtk.TREE_VIEW_COLUMN_AUTOSIZE)
    tree_view.append_column (column)

    model.set_sort_column_id (FwdZone.COLUMN_TEXT, gtk.SORT_ASCENDING)
    model.set_sort_func(FwdZone.COLUMN_TEXT,on_sort)


def setup_add_reverse_treeview():
    tree_view=xml.get_widget ('rr_add_reverse_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING,gobject.TYPE_PYOBJECT)
    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererPixbuf(), pixbuf=COLUMN_PIXBUF)
    tree_view.append_column (column)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText(), text=COLUMN_TEXT)
    tree_view.append_column (column)
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)

    tree_view=xml.get_widget ('rr_cname_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING)
    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererPixbuf(), pixbuf=COLUMN_PIXBUF)
    tree_view.append_column (column)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText(), text=COLUMN_TEXT)
    tree_view.append_column (column)
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)

    tree_view=xml.get_widget ('rr_mx_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING)
    tree_view.set_model (model)
    column = gtk.TreeViewColumn (None, gtk.CellRendererPixbuf(), pixbuf=COLUMN_PIXBUF)
    tree_view.append_column (column)
    column = gtk.TreeViewColumn (None, gtk.CellRendererText(), text=COLUMN_TEXT)
    tree_view.append_column (column)
    model.set_sort_column_id(COLUMN_TEXT, gtk.SORT_ASCENDING)        
    model.set_sort_func(COLUMN_TEXT,on_sort)
    

def setup_zone_ns_treeview():
    tree_view = xml.get_widget ('zone_ns_treeview')
    model = gtk.ListStore (gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,gobject.TYPE_STRING,gobject.TYPE_STRING)
    tree_view.set_model (model)

    column = gtk.TreeViewColumn (_("Filler"), gtk.CellRendererText (), text=COLUMN_TEXT)
    column.set_sizing (gtk.TREE_VIEW_COLUMN_AUTOSIZE)
    tree_view.append_column (column)

    model.set_sort_column_id (COLUMN_TEXT, gtk.SORT_ASCENDING)
    model.set_sort_func(COLUMN_TEXT,on_sort)
    tree_view.get_selection().connect ("changed",
                                       on_generic_tree_view_selection_changed,
                                       xml.get_widget ('zone_ns_edit_button'), xml.get_widget ('zone_ns_delete_button'),xml.get_widget ('bindconf_add_record_button'))
    tree_view.connect ("row_activated",
                       on_generic_tree_view_row_activated, on_zone_ns_edit_button_clicked)

    
def setup_dialogs ():
    setup_zone_mx_treeview()

    setup_zone_ns_treeview()

    setup_add_reverse_treeview()

    setup_slave_zone_treeview()

    setup_mx_treeview()
    
    setup_cname_treeview()
    
def main ():
    xml.signal_autoconnect (
        {
        'on_bindconf_delete_event' : on_bindconf_delete_event,
        'on_new_activate' : on_new_activate,
        'on_properties_activate' : on_properties_activate,
        'on_delete_activate' : on_delete_activate,
        'on_add_record_activate' : on_add_record_activate,
        'on_exit_activate' : on_exit_activate,
        'on_apply_and_save_activate' : on_apply_and_save_activate,
        "on_manual_activate" : on_manual_activate,
        'on_about_activate' : on_about_activate,
        'on_bindconf_add_button_clicked' : on_bindconf_add_button_clicked,
        'on_bindconf_edit_button_clicked' : on_bindconf_edit_button_clicked,
        'on_bindconf_delete_button_clicked' : on_bindconf_delete_button_clicked,
        'on_bindconf_add_record_button_clicked' : on_bindconf_add_record_button_clicked,

        "on_fwd_zone_rbutton_toggled" : on_zone_type_toggled,
        "on_rev_zone_rbutton_toggled" : on_zone_type_toggled,
        "on_slave_zone_rbutton_toggled" : on_zone_type_toggled,

        #slave
        'on_slave_zone_masters_add_button_clicked' : on_slave_zone_masters_add_button_clicked,
        'on_slave_zone_masters_delete_button_clicked' : on_slave_zone_masters_delete_button_clicked,
        'on_slave_zone_masters_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9. ]+$'),
        'on_slave_zone_file_entry_insert_text' : (on_generic_entry_insert_text, r'^[^/ ]+$'),

        #rev
        'on_rev_zone_changed':on_rev_zone_changed,
        'on_rev_zone_name_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9.]+$'),
        'on_rev_zone_name_entry_changed' : on_rev_zone_name_entry_changed,
        'on_rev_zone_pns_changed' : on_rev_zone_pns_changed,
        'on_rev_zone_file_entry_insert_text' : (on_generic_entry_insert_text, r'^[^/ ]+$'),
        'on_rev_zone_soa_button_clicked':on_rev_zone_soa_button_clicked,
        'on_rev_zone_add_button_clicked' : on_rev_zone_add_button_clicked,
        'on_rev_zone_edit_button_clicked' : on_rev_zone_edit_button_clicked,
        'on_rev_zone_delete_button_clicked' : on_rev_zone_delete_button_clicked,

        'on_rev_master_ns_treeview_select_row' : (on_generic_treeview_select_row, xml.get_widget ('rev_master_ns_edit_button'), xml.get_widget ('rev_master_ns_delete_button')),
        'on_rev_master_ns_treeview_unselect_row' : (on_generic_treeview_unselect_row, xml.get_widget ('rev_master_ns_edit_button'), xml.get_widget ('rev_master_ns_delete_button')),
        'on_rev_master_ns_add_button_clicked' : on_rev_master_ns_add_button_clicked,
        'on_rev_master_ns_edit_button_clicked' : on_rev_master_ns_edit_button_clicked,
        'on_rev_master_ns_delete_button_clicked' : on_rev_master_ns_delete_button_clicked,
        'on_rev_zone_contact_entry_changed' : on_rev_zone_changed,
        'on_rev_zone_set_button_clicked' : on_rev_zone_set_button_clicked,

        #fwd
        'on_fwd_zone_set_button_clicked' : on_fwd_zone_set_button_clicked,
        'on_fwd_zone_soa_button_clicked' : on_fwd_zone_soa_button_clicked,
        'on_fwd_zone_name_entry_changed' : on_fwd_zone_name_entry_changed,
        'on_fwd_zone_file_entry_insert_text' : (on_generic_entry_insert_text, r'^[^/ ]+$'),
        'on_fwd_zone_file_entry_changed' : on_fwd_zone_changed,
        'on_fwd_zone_add_button_clicked' : on_fwd_zone_add_button_clicked,
        'on_fwd_zone_edit_button_clicked' : on_fwd_zone_edit_button_clicked,
        'on_fwd_zone_delete_button_clicked' : on_fwd_zone_delete_button_clicked,
        'on_fwd_zone_contact_entry_changed' : on_fwd_zone_changed,

        'on_soa_refresh_entry_changed' : zone_changed,
        'on_soa_retry_entry_changed' : zone_changed,
        'on_soa_expire_entry_changed' : zone_changed,
        'on_soa_minimum_entry_changed' : zone_changed,
        'on_serial_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9]+$'),
        'on_soa_refresh_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9]+$'),
        'on_soa_retry_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9]+$'),
        'on_soa_expire_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9]+$'),
        'on_soa_minimum_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9]+$'),

        'on_mx_priority_entry_insert_text' : (on_generic_entry_insert_text, r'^[0-9]+$'),
        'on_mx_button_toggled' : on_mx_button_toggled,
        'on_rr_toggled' : on_rr_toggled,

        'on_a_treeview_select_row' : (on_generic_treeview_select_row, xml.get_widget ('a_edit_button'), xml.get_widget ('a_delete_button')),
        'on_a_treeview_unselect_row' : (on_generic_treeview_unselect_row, xml.get_widget ('a_edit_button'), xml.get_widget ('a_delete_button')),
        'on_zone_ns_treeview_select_row' : (on_generic_treeview_select_row, xml.get_widget ('zone_ns_edit_button'), xml.get_widget ('zone_ns_delete_button')),
        'on_zone_ns_treeview_unselect_row' : (on_generic_treeview_unselect_row, xml.get_widget ('zone_ns_edit_button'), xml.get_widget ('zone_ns_delete_button')),
        'on_zone_ns_add_button_clicked' : on_zone_ns_add_button_clicked,
        'on_zone_ns_edit_button_clicked' : on_zone_ns_edit_button_clicked,
        'on_zone_ns_delete_button_clicked' : on_zone_ns_delete_button_clicked,
        'on_zone_mx_treeview_select_row' : (on_generic_treeview_select_row, xml.get_widget ('zone_mx_edit_button'), xml.get_widget ('zone_mx_delete_button')),
        'on_zone_mx_treeview_unselect_row' : (on_generic_treeview_unselect_row, xml.get_widget ('zone_mx_edit_button'), xml.get_widget ('zone_mx_delete_button')),
        'on_zone_mx_add_button_clicked' : on_zone_mx_add_button_clicked,
        'on_zone_mx_edit_button_clicked' : on_zone_mx_edit_button_clicked,
        'on_zone_mx_delete_button_clicked' : on_zone_mx_delete_button_clicked,

        'hostname_check' : (on_generic_entry_insert_text, hostname_pattern),
        'on_bindconf_treeview_expand_row' : on_bindconf_treeview_expand_row
        })
    setup_main_tree ()
    setup_dialogs ()
    xml.get_widget ('bindconf').set_title (FORMALNAME)
    xml.get_widget ('bindconf').show_all ()
    gtk.mainloop()

def duplicate_rev_address(zone,newhost,address):
    ptrlist = zone.getPTRList ()
    for ptr in ptrlist:
        ip = str(ptr.getIp ())
        host = ptr.getHost ()
        if ip==address:
            return 1
        if host==newhost:
            return 2
    return 0
    
def add_rev_zone_address_dialog (dialog,zone):
    text=getZoneSubnet(zone)
    ztext=add_dot (text)
    xml.get_widget ('rev_master_address_label').set_text (ztext)
    spin = xml.get_widget ('rev_master_address_spin')
    entry = xml.get_widget ('rev_master_address_entry')
    notebook=xml.get_widget ('rev_master_notebook')

    spin.set_text ("")
    entry.set_text ("")
    ptr = None

    while 1:
        status = dialog.run ()
        if status != gtk.RESPONSE_OK:
            dialog.hide ()
            return status

        i = notebook.get_current_page()
        if i == 0:
            ip = spin.get_text ()
            host = entry.get_text ()
            if ip == "":
                generic_error_dialog (_("You must enter an octet."), dialog, broken_widget=spin)
                continue
            if host == "":
                generic_error_dialog (_("You must enter a hostname."), dialog, broken_widget=entry)
                continue

            try:
                host=add_dot(host)
                brw = spin
                Zone.testIp(ztext+ip)
                brw = entry
                Zone.testHost(host)
            except TestError, e:
                generic_error_dialog (e.args, dialog, broken_widget=brw)
                continue
        

            if duplicate_rev_address(zone,add_dot (entry.get_text ()),ip)==1:
                generic_error_dialog (_("A reverse address record with that octet or hostname already exists"), dialog, broken_widget=spin)
                continue
            zone.zone.addPTR(host,ip)
        elif i == 1:
            broken_widget = xml.get_widget ('rev_master_nameserver_host_entry')
            host = broken_widget.get_text ()
            Zone.testHost(host)
            broken_widget = xml.get_widget ('rev_master_nameserver_domain_entry')
            applies_to = broken_widget.get_text ()
            Zone.testAppliesTo(applies_to)
            #FIXME: check this value
            dialog.hide ()
            zone.zone.addNS(host,applies_to)
        zone.this_dirty=TRUE
        dialog.hide ()
            
        update.set(TRUE)
        return status

# make ctrl-C work
if __name__ == "__main__":
    signal.signal (signal.SIGINT, signal.SIG_DFL)
    main ()


