#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006  Donald N. Allingham
# Copyright (C) 2008       Willem van Engen
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# History:
#   20080105  Encode data properly for xml.
#   20080103  Willem van Engen's initial release. Much rewritten, general
#             filter support, address without lon/lat, customizable title.
#             Family events are missing though.
#   2006      Donald Allingham's release



"""
Contains the interface to allow to write place data. 
One backend for writing is supported: the KML file format used by google earth

info: bm at cage dot UGent dot be, dev-gramps@willem.engen.nl
"""

#-------------------------------------------------------------------------
#
# load standard python libraries
#
#-------------------------------------------------------------------------
import time
import os
import codecs
from gettext import gettext as _
from xml.sax import saxutils
import Utils

#-------------------------------------------------------------------------
#
# load GRAMPS libraries
#
#-------------------------------------------------------------------------
import RelLib

#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
log = logging.getLogger(".WriteGreographicData")


#-------------------------------------------------------------------------
#
#   backend: KML writer for the actual writing of geographic data
#
#-------------------------------------------------------------------------
class KmlWriter:
    """
    Writes output to a KML file.
    """

    def __init__(self, title, placemarks=(), placestyles={}):
        """
        Initializes, but does not write, a KML file.

        @param title: title of the KML group
        @param placemarks: a list of placemarks to write. Each placemark
            is a dictionary, contaning the items:
            (required:) title, shortdesc, longdesc_html, style;
            (optional:) date, dateend, address, lon, lat
        @param placestyles: different styles to show data in kml.
            A dictionary with key stylename, data style.
            TODO: Currently only the keys are used, indicating image files.

         """
        self.title = title
        self.styles = placestyles
        self.places = placemarks
        
    def write(self,filename):
        """
        Write the data to the specified file.
        """
        base = os.path.dirname(filename)
        if os.path.isdir(base):
            if not os.access(base,os.W_OK) or not os.access(base,os.R_OK):
                ErrorDialog(_('Failure writing %s') % filename,
                            _("The file cannot be saved because you do "
                              "not have permission to write to the directory. "
                              "Please make sure you have write access to the "
                              "directory and try again."))
                return 0
            
        if os.path.exists(filename):
            if not os.access(filename,os.W_OK):
                ErrorDialog(_('Failure writing %s') % filename,
                            _("The file cannot be saved because you do "
                              "not have permission to write to the file. "
                              "Please make sure you have write access to the "
                              "file and try again."))
                return 0
        
        self.fileroot = os.path.dirname(filename)

        try:
            g = open(filename,"w")
        except IOError,msg:
            ErrorDialog(_('Failure writing %s') % filename,msg)
            return 0
        self.g = codecs.getwriter("utf8")(g)

        self._write_kml_data()
        g.close()
        return 1

    def write_handle(self,handle):
        """
        Write the data to the specified file handle.
        """
        g = handle

        self.g = codecs.getwriter("utf8")(g)

        self._write_kml_data()
        g.close()
        return 1
            
    def _write_kml_data(self):
        """
        Write the already opened KML file.
        """
        date = time.localtime(time.time())

        place_len = len(self.places)

        self.g.write('<?xml version="1.0" encoding="utf-8"?>\n')
        self.g.write('<kml xmlns="http://earth.google.com/kml/2.1">\n')
        # some info
        self.g.write('<!-- created date="%04d-%02d-%02d\" -->\n'%
                     (date[0],date[1],date[2]) )

        # start the document
        self.g.write("  <Document>\n")
        # set the name of the document
        self.g.write("    <name>%s</name>" %(self.title))
        # set the default styles used; use unique values from eventstyle lists
        for style in self.styles.keys():
            self._write_style('gramps'+style, 'event'+style+'.png')

        # set all placemarks
        for placemark in self.places:
            self._write_placemark(placemark)

        self.g.write("\n")
        self.g.write("  </Document>\n")
        self.g.write("</kml> \n")

    def _write_style(self,id,icon):
        """
        Writes a style to the KML file

        @param id: id of the style
        @type id: string
        @param icon: icon filename associated with this style, located
            in <image_dir>/KML/. Specify None if no icon is present.
        @type icon: string
        """

        # XXX according to the KML 2.1 spec, Icon should have a single href
        #     child element. I haven't been able though to reference local
        #     images in this way though.

        self.g.write("""
          <Style id="%(id)s"> 
            <BalloonStyle>
              <!-- a background color for the balloon -->
              <color>00ffffff</color>
              <!-- styling of the balloon text -->
              <text><![CDATA[$[description]]]></text>
            </BalloonStyle>""" %{'id': id} )
        if icon:
            self.g.write("""
            <IconStyle id="grampsIcon">
              <color>ffffffff</color>
              <colorMode>normal</colorMode>
              <scale>1</scale>
              <Icon>%(icon)s</Icon> 
              <hotSpot x="0.5" y="0.5" xunits="fraction" yunits="fraction"/>
            </IconStyle>""" % { \
                  'icon': saxutils.escape(os.path.join(const.image_dir, 'KML',icon))} )
        self.g.write("""
          </Style>""")

    def _write_placemark(self,placemark):
        """
        Writes a placemark to the KML file

        @param placemark: placemark properties
        """

        #  write KML placemark
        self.g.write("""
            <Placemark>
              <name>%(name)s</name>
              <visibility>1</visibility>
              <open>1</open>
              <Snippet>%(snip)s</Snippet>
              <description>%(desc)s</description>
              <styleUrl>gramps%(style)s</styleUrl>""" % { \
                  'name': saxutils.escape(placemark['title']), \
                  'snip': saxutils.escape(placemark['shortdesc']), \
                  'desc': placemark['longdesc_html'], \
                  'style': saxutils.escape(placemark['style']) } )

        if placemark.has_key('date') and placemark['date']:
            if placemark.has_key('dateend') and placemark['dateend']:
                # timespan
                self.g.write("""
              <TimeSpan>
                <begin>%(begin)s</begin>
                <end>%(end)s</end>
              </TimeSpan>""" % { \
                  'begin': saxutils.escape(placemark['date']), \
                  'end': saxutils.escape(placemark['dateend']) } )
            else:
                # timestamp
                self.g.write("""
              <TimeStamp><when>%(date)s</when></TimeStamp>""" % { \
                  'date': saxutils.escape(placemark['date']) } )

        if placemark.has_key('address') and placemark['address']:
            self.g.write("""
              <address>%(address)s</address>""" % { \
                  'address': saxutils.escape(placemark['address']) })
        if placemark.has_key('lon') and placemark.has_key('lat') and \
           placemark['lon'] and placemark['lat']:
            self.g.write("""
              <Point>
                <coordinates>%(lon).14f,%(lat).14f</coordinates>
              </Point>""" % { \
                  'lon': placemark['lon'], \
                  'lat': placemark['lat'] } )
        self.g.write("""
            </Placemark>""")


#------------------------------------------------------------------------
#
# GNOME/gtk
#
#------------------------------------------------------------------------
import gtk

#-------------------------------------------------------------------------
#
# load GRAMPS libraries
#
#-------------------------------------------------------------------------

import const
from QuestionDialog import ErrorDialog
from PluginUtils import register_report
from ReportBase import CATEGORY_CODE, MODE_GUI, Report, ReportOptions
from ReportBase._ReportDialog import ReportDialog
from NameDisplay import displayer as _nd
from DateHandler import displayer as _dd
#import DateHandler
import PlaceUtils
from Filters import GenericFilter, Rules

#------------------------------------------------------------------------
#
# Report class
#
#------------------------------------------------------------------------
class GeographicData:

    def __init__(self,database,person,options_class):
        self.database = database
        self.start_person = person

        options = options_class.handler.options_dict


#------------------------------------------------------------------------
#
# Constant options items
#
#------------------------------------------------------------------------

class _options:
    # internal ID, english option name (for cli), localized option name (for gui)
    formats = (
        ("kml", "Google Earth KML", _("Google Earth KML"), "application/kml"),
    )


#check if googleearth is installed. 
#  --> problem, googleearth is normally installed locally, not in the PATH variable... TODO
if os.sys.platform == "win32":
    _gge_found = Utils.search_for("googleearth.exe")
else:
    _gge_found = Utils.search_for("googleearth")




#------------------------------------------------------------------------
#
# Options class 
#
#------------------------------------------------------------------------
class GeographicDataOptions(ReportOptions):

    """
    Defines options and provides handling interface.
    """

    def __init__(self,name,person_id=None):
        ReportOptions.__init__(self,name,person_id)

    def set_new_options(self):
        # Options specific for this report
        self.options_dict = {
            'unknownplace' : 0,
            'unknowndate' : 1,
            'filter' : 0,
            'titleformat' : 1,
        }
        self.options_help = {
            'unknownplace': ("=0/1","Whether to show events with unknown location.",
                            ["Show events with known location","Show events with or without a location"],
                            False),
            'unknowndate':  ("=0/1","Whether to show events with no date specified.",
                            ["Show only events with known date", "Show events with or without date"],
                            False),
            'titleformat':  ("=str","What to use as placemark titles.",
                            self._get_report_nameformatters_sample(),
                            False),
        }
        
        
    def make_doc_menu(self,dialog,active=None):
        pass
    
    def add_list(self, options, default):
        "returns combobox of given options and default value"
        box = gtk.ComboBox()
        store = gtk.ListStore(str)
        box.set_model(store)
        cell = gtk.CellRendererText()
        box.pack_start(cell,True)
        box.add_attribute(cell,'text',0)
        for i in range(len(options)):
            store.append(row=[options[i]])
            if i == default:
                box.set_active(i)
        return box

    def add_user_options(self,dialog):
        # Content of the options tab

        msg = _("Placemark title format")
        self.title_format = self.add_list(
                        self._get_report_nameformatters_sample(),
                        self.options_dict['titleformat'])
        dialog.add_option(None,
                        self.title_format,
                        _("Placemark title format"))
       
        msg = _("Include Events with no place given")
        self.include_place_unknown = gtk.CheckButton(msg)
        self.include_place_unknown.set_active(self.options_dict['unknownplace'])
        dialog.add_option(None,
                        self.include_place_unknown,
                        _("Include events which have no place specified."))

        msg = _("Include Events with no date given")
        self.include_date_unknown = gtk.CheckButton(msg)
        self.include_date_unknown.set_active(self.options_dict['unknowndate'])
        dialog.add_option(None,
                        self.include_date_unknown,
                        _("Include events which have no date attached."))

    def parse_user_options(self,dialog):
        self.options_dict['titleformat'] = \
            int(self.title_format.get_active())
        self.options_dict['unknownplace'] = \
            int(self.include_place_unknown.get_active())
        self.options_dict['unknowndate'] = \
            int(self.include_date_unknown.get_active())

    def get_report_filters(self,person):
        """Set up the list of possible content filters."""
        # thank you, IndivComplete.py :)
        if person:
            name = _nd.display(person)
            gramps_id = person.get_gramps_id()
        else:
            name = 'PERSON'
            gramps_id = ''

        filt_id = GenericFilter()
        filt_id.set_name(name)
        filt_id.add_rule(Rules.Person.HasIdOf([gramps_id]))

        all = GenericFilter()
        all.set_name(_("Entire Database"))
        all.add_rule(Rules.Person.Everyone([]))

        des = GenericFilter()
        des.set_name(_("Descendants of %s") % name)
        des.add_rule(Rules.Person.IsDescendantOf([gramps_id,1]))

        ans = GenericFilter()
        ans.set_name(_("Ancestors of %s") % name)
        ans.add_rule(Rules.Person.IsAncestorOf([gramps_id,1]))

        com = GenericFilter()
        com.set_name(_("People with common ancestor with %s") % name)
        com.add_rule(Rules.Person.HasCommonAncestorWith([gramps_id]))

        the_filters = [filt_id,all,des,ans,com]
        from Filters import CustomFilters
        the_filters.extend(CustomFilters.get_filters('Person'))
        return the_filters

    def get_report_nameformatters(self):
        """ Returns a list of functions that convert a name into a string """
        # Note that the code below uses string[:1] instead of string[0] to
        #   obtain a name's first letter. This avoids an IndexError and
        #   returns the empty string when string has length zero.
        return [
            # Doe, John Chris
            lambda name: \
                ' '.join(filter(None,
                    [name.get_surname_prefix(), name.get_surname()])) \
                + ', ' + name.get_first_name(),
            # Doe, John
            lambda name: \
                ' '.join(filter(None,
                    [name.get_surname_prefix(), name.get_surname()])) \
                + ', ' + name.get_first_name().split()[0],
            # Doe, J.C.
            lambda name: \
                ' '.join(filter(None,
                    [name.get_surname_prefix(), name.get_surname()])) \
                + ', ' + \
                ''.join(map(lambda x:x[:1]+'.',name.get_first_name().split())),
            # Doe, J.
            lambda name: \
                ' '.join(filter(None,
                    [name.get_surname_prefix(), name.get_surname()])) \
                + ', ' + name.get_first_name()[:1],
            # John Chris Doe
            lambda name: ' '.join(filter(None, [ \
                name.get_first_name(), \
                name.get_surname_prefix(), name.get_surname()])), \
            # John Doe
            lambda name: ' '.join(filter(None, [ \
                name.get_first_name().split()[0], \
                name.get_surname_prefix(), name.get_surname()])), \
            # J.C. Doe
            lambda name: ' '.join(filter(None, [ \
                ''.join(map(lambda x:x[:1]+'.',name.get_first_name().split())), \
                name.get_surname_prefix(), name.get_surname()])), \
            # J. Doe
            lambda name: ' '.join(filter(None, [ \
                name.get_first_name()[:1] + '.', \
                name.get_surname_prefix(), name.get_surname()])), \
        ]

    def _get_report_nameformatters_sample(self):
        """Return array with sample names for nameformatters"""

        # person with all features that make distinguishing names
        name = RelLib.Name()
        name.set_call_name(_('Joe'))
        name.set_first_name(_('John Christian'))
        name.set_surname(_('Doe'))

        formatters = self.get_report_nameformatters()
        return [ formatters[i](name) for i in range(len(formatters)) ]

#-------------------------------------------------------------------------
#
#    The Dialog class
#
#-------------------------------------------------------------------------

class GeographicDataDialog(ReportDialog):
    def __init__(self,dbstate,uistate,person):
        self.database = dbstate.db
        self.person = person
        name = "map_view"
        translated_name = _("Map View (Google Earth export)")
        self.options_class = GeographicDataOptions(name)
        self.category = CATEGORY_CODE
        ReportDialog.__init__(self,dbstate,uistate,person,self.options_class,
                              name,translated_name)
        response = self.window.run()
        if response == gtk.RESPONSE_OK:
            try:
                self.make_report()
            except (IOError,OSError),msg:
                ErrorDialog(str(msg))
        elif response == gtk.RESPONSE_DELETE_EVENT:
            return
        self.close()

    def make_doc_menu(self,active=None):
        """Build a one item menu of document types that are
        appropriate for this report."""
        self.format_menu = FormatComboBox()
        self.format_menu.set()

    def make_document(self):
        """Do Nothing.  This document will be created in the
        make_report routine."""
        pass
    
    def setup_style_frame(self):
        """The style frame is not used in this dialog."""
        pass

    def parse_style_frame(self):
        """The style frame is not used in this dialog."""
        pass

    def doc_type_changed(self, obj):
        """The doc type is of no importance in this dialog."""
        pass

    def setup_paper_frame(self):
        """No need for Paper Options in this dialog"""
        pass
    def parse_paper_frame(self):
        """No need for Paper Options in this dialog"""
        pass

    def make_report(self):
        """Create the object that will produce the GraphViz file."""
        GeoGraphicDataExtract(self.database,self.person,self.options_class)


#------------------------------------------------------------------------
#
# Combo Box classes
#
#------------------------------------------------------------------------
class FormatComboBox(gtk.ComboBox):
    """
    Format combo box class.
    
    Trivial class supporting only one format.
    """

    def set(self,tables=0,callback=None,obj=None,active=None):
        self.store = gtk.ListStore(str)
        self.set_model(self.store)
        cell = gtk.CellRendererText()
        self.pack_start(cell,True)
        self.add_attribute(cell,'text',0)
        self.store.append(row=["Google Earth (kml)"])
        self.set_active(0)

    def get_label(self):
        return "Google Earth (kml)"

    def get_reference(self):
        return None

    def get_paper(self):
        return 1

    def get_styles(self):
        return 0

    def get_ext(self):
        return '.kml'

    def get_printable(self):
        _apptype = _options.formats[self.get_active()][3]
        print_label = None
        try:
            mprog = Mime.get_application(_apptype)
    
            if Utils.search_for(mprog[0]):
                print_label = _("Open in %(program_name)s") % { 'program_name':
                                                        mprog[1]}
            else:
                print_label = None
        except:
            print_label = None

        return print_label

    def get_clname(self):
        return 'kml'

class GraphicsFormatComboBox(gtk.ComboBox):
    """
    Format combo box class for graphical (not codegen) report.
    """

    def set(self,active=None):
        self.store = gtk.ListStore(str)
        self.set_model(self.store)
        cell = gtk.CellRendererText()
        self.pack_start(cell,True)
        self.add_attribute(cell,'text',0)
        active_index = 0
        index = 0
        for item in _options.formats:
            self.store.append(row=[item[2]])
            if active == item[0]:
                active_index = index
            index = index + 1
        self.set_active(active_index)

    def get_label(self):
        return _options.formats[self.get_active()][2]

    def get_reference(self):
        return EmptyDoc

    def get_paper(self):
        return 0

    def get_styles(self):
        return 0

    def get_ext(self):
        return '.%s' % _options.formats[self.get_active()][0]

    def get_format_str(self):
        return _options.formats[self.get_active()][0]

    def get_printable(self):
        _apptype = _options.formats[self.get_active()][3]
        print_label = None
        try:
            mprog = Mime.get_application(_apptype)
            if Utils.search_for(mprog[0]):
                print_label = _("Open in %(program_name)s") % { 'program_name':
                                                                mprog[1] }
            else:
                print_label = None
        except:
            print_label = None
        return print_label

    def get_clname(self):
        return 'print'

#------------------------------------------------------------------------
#
# Empty class to keep the BaseDoc-targeted format happy
#
#------------------------------------------------------------------------
class EmptyDoc:
    def __init__(self,styles,type,template,orientation,source=None):
        self.print_req = 0

    def init(self):
        pass
    
    def print_requested(self):
        self.print_req = 1


#------------------------------------------------------------------------
#
#  Class that extracts the geographical data corresponding to the options
#    and sends that to the backend
#
#------------------------------------------------------------------------

class GeoGraphicDataExtract:
  
    # EventType -> icon mapping, see _get_style for details.
    #     This is used in KML style name and icon filename.
    _eventstyles_gender = {
        RelLib.EventType.UNKNOWN: '',
        RelLib.EventType.ADOPT: 'birth',
        RelLib.EventType.BIRTH: 'birth',
        RelLib.EventType.DEATH: 'death',
        RelLib.EventType.ADULT_CHRISTEN: 'bapt',
        RelLib.EventType.BAPTISM: 'bapt',
        RelLib.EventType.BURIAL: 'burial',
        RelLib.EventType.CREMATION: 'burial',
    }
    _eventstyles_neutral = {
        RelLib.EventType.MARRIAGE: 'marriage',
        RelLib.EventType.MARR_CONTR: 'marriage',
        RelLib.EventType.MARR_LIC: 'marriage',
        #RelLib.EventType.DIVORCE: 'divorce',
        #RelLib.EventType.DIV_FILING: 'divorce',
        RelLib.EventType.MARR_ALT: 'marriage',
    }

    def __init__(self,database,person,options_class):
        """
        Creates GeoGraphicDataExtract object that produces data for the report.
        
        The arguments are:

        database        - the GRAMPS database instance
        person          - currently selected person
        options_class   - instance of the Options class for this report

        This report needs the following parameters (class variables)
        that come in the options class.
        
           unknowns: if place has unknown location/event has unknown location, 
                       export it nevertheless
                       
        """
        self.database = database
        self.start_person = person
        
        # get options
        options = options_class.handler.options_dict
        self.requireDate = not options['unknowndate']
        self.requirePlace = not options['unknownplace']
        self.nameformatter = options_class.get_report_nameformatters()[options['titleformat']]

        # what persons to include
        filter_num = options_class.get_filter_number()
        filters = options_class.get_report_filters(person)
        self.filter = filters[filter_num]

        self.filename = options_class.get_output()
        
        print 'filter is',filter_num, \
                ', requireDate is', self.requireDate, \
                ', requirePlace is', self.requirePlace, \
                ', to filename',self.filename
        
        self._obtain_data()
        self._writetobackend()


    def _obtain_data(self):
        """we perform the needed lookup in the database. 
          output needed, a dictionary of placemarks, with index the placehandle
            and a placemark being 
        """

        # all places to be written
        self.placemarks = []
        # styles used, they may need to be written before places
        self.usedstyles = {}
        
        # Get list of wanted persons
        plist = self.database.get_person_handles(sort_handles=False)
        if self.filter:
            ind_list = self.filter.apply(self.database,plist)
        else:
            ind_list = plist

        # Gather events of persons, gather families.
        # We want one placemark for each related event, that's why events
        # and families are gathered first, and then placemark date is
        # generated for each unique event.
        family_list = {}
        eventref_person_list = {}
        for person_handle in ind_list:
            self.obtain_events_person(person_handle)

        # pretty title
        self.title = self.filter.get_name()
        
    def obtain_events_person(self, person_handle):
        print 'get events for person ' , person_handle
        person = self.database.get_person_from_handle(person_handle)
        if not person:
            return

        event_ref_list = person.get_event_ref_list()
        for event_ref in event_ref_list:
            self.make_event_placemark(event_ref, person)

    def make_event_placemark(self, event_ref, person):
            #the event_ref holds the role the person plays in an event
            event = self.database.get_event_from_handle(event_ref.get_reference_handle())
            place = self.database.get_place_from_handle(event.get_place_handle())
            date = event.get_date_object()

            # data is gathered here, this is passed to the writer class
            placemark = {}

            placemark['title'] = self._get_display_name(person)
            if date:
                if date.is_regular():
                    placemark['date'] = str(date)
                elif date.is_compound():
                    dateparts = str(date).split(' - ')
                    placemark['date'] = dateparts[0]
                    placemark['dateend'] = dateparts[1]

            # description pop-up
            placetitle = ''
            if place:
                placetitle = place.get_title()
            placemark['longdesc_html'] = _('<h1>%(name)s</h1>' \
                + '<b>Event</b>: %(eventtype)s,  '\
                + '<b>Role</b>: %(role)s<br/>' \
                + '<b>Place</b>: %(place)s<br/>') %{ \
                    'name': saxutils.escape( \
                              _nd.display_name(person.get_primary_name())), \
                    'eventtype': saxutils.escape(str(event.get_type())), \
                    'role': saxutils.escape(str(event_ref.get_role())), \
                    'place': saxutils.escape(placetitle) }
            if date:
                placemark['longdesc_html'] += _('<b>Date</b>: %s') % \
                    saxutils.escape(str(date))
            placemark['longdesc_html'] += '<br/>' + \
                saxutils.escape(event.get_description())

            # short description with label & place attributes
            placemark['shortdesc'] = ''
            if event.get_description():
                placemark['shortdesc'] += event.get_description()
            if place:
                if place.get_title():
                    if placemark['shortdesc']:
                        placemark['shortdesc'] += '\n'
                    placemark['shortdesc'] += place.get_title()

                # location
                placemark['lon'] = place.get_longitude()
                placemark['lat'] = place.get_latitude()
                placemark['address'] = \
                    self._location2address(place.get_main_location())
                if not placemark['address']:
                    placemark['address'] = place.get_title()

            # style
            # TODO primary person should determine style; do we need to
            #      include events with people who aren't the primary person?
            placemark['style'] = self._get_style(person, event)

            # we add to dictionary with every place occuring only once
            self._add_placemark(placemark)
            
    def _add_placemark(self, placemark) :
            """
            Adds a placemark to the list.
            TODO: currently it's just added. But when no dates are used,
                  we may want to have a single place for multiple events.

            @param placemark: dictionary with placemark data
            """

            # filter out unwanted items
            if self.requirePlace:
                if not placemark.has_key('address') and \
                   ( not placemark.has_key('lon') or \
                     not placemark.has_key('lat') ):
                    return None;
            if self.requireDate:
                if not placemark.has_key('date'):
                    return None;

            self.usedstyles[placemark['style']] = True
            self.placemarks.append(placemark)
            return placemark

    def _get_style(self, person, event):
        type = int(event.get_type())
        # try non gender-related first
        if self._eventstyles_neutral.has_key(type):
            print '  got neutral: ',self._eventstyles_neutral[type]
            return self._eventstyles_neutral[type]
        # gender-related style, fallback to UNKNOWN
        if not self._eventstyles_gender.has_key(type):
            print '  falling back to unknown'
            type = RelLib.EventType.UNKNOWN
        if person.get_gender() is RelLib.Person.MALE:
            return 'M'+self._eventstyles_gender[type]
        if person.get_gender() is RelLib.Person.FEMALE:
            return 'F'+self._eventstyles_gender[type]
        print '  got unknown: ',self._eventstyles_gender[type]
        return 'U'+self._eventstyles_gender[type]

    def _get_display_name(self, person):
        """
        Returns the display name for a person, for use as title exported
        file.

        @param person: person to get name for
        @type person: RelLib.Person
        @return: name string
        """
        return self.nameformatter(person.get_primary_name());

    def _location2address(self, location):
        """
        Returns an address string for a GRAMPS location. Country is required.

        @param location: where
        @type location: RelLib.Location
        @return: address string, or None
        """
        address = ''

        if not location:
            return None

        if location.get_street():
            address += location.get_street() + ', '
        if location.get_city():
            address += location.get_city() + ', '
        if location.get_state():
            address += location.get_state() + ', '
        if location.get_postal_code():
            address += location.get_postal_code() + ', '
        # country is required
        if location.get_country():
            address += location.get_country()
        else:
            return None

        return address

    def _writetobackend(self):
         """ write to the actual backend by calling it's writer correctly
         """
         kmlfile = KmlWriter(self.title, self.placemarks, self.usedstyles)
         kmlfile.write(self.filename)


#------------------------------------------------------------------------
# 
#    Report registration
#
#------------------------------------------------------------------------


register_report(
    name = 'kmlexport',
    category = CATEGORY_CODE,
    report_class = GeographicDataDialog,
    options_class = GeographicDataOptions,
    modes = MODE_GUI ,
    translated_name = _("KML Google Earth Export"),
    status = _("UnStable"),
    description = _("Creates a kml file that can be played/opened in Google Earth."),
    author_name = "Benny Malengier, Willem van Engen",
    author_email = "bm@cage.UGent.be, dev-gramps@willem.engen.nl"
    )

# vim:expandtab:ts=4:sw=4:
