svn: r8622
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| # | ||||
| # Gramps - a GTK+/GNOME based genealogy program | ||||
| # | ||||
| # Copyright (C) 2004-2006  Donald N. Allingham | ||||
| # Copyright (C) 2004-2007  Donald N. Allingham | ||||
| # | ||||
| # 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 | ||||
| @@ -38,6 +38,7 @@ import re | ||||
| # | ||||
| #------------------------------------------------------------------------- | ||||
| from RelLib import Name | ||||
| from Errors import NameDisplayError | ||||
|  | ||||
| try: | ||||
|     import Config | ||||
| @@ -243,19 +244,19 @@ class NameDisplay: | ||||
|  | ||||
|  | ||||
|     def _gen_raw_func(self, format_str): | ||||
| 	"""The job of building the name from a format string is rather | ||||
| 	expensive and it is called lots and lots of times. So it is worth | ||||
| 	going to some length to optimise it as much as possible.  | ||||
|         """The job of building the name from a format string is rather | ||||
|         expensive and it is called lots and lots of times. So it is worth | ||||
|         going to some length to optimise it as much as possible.  | ||||
|  | ||||
| 	This method constructs a new function that is specifically written  | ||||
| 	to format a name given a particualar format string. This is worthwhile | ||||
| 	because the format string itself rarely changes, so by caching the new | ||||
| 	function and calling it directly when asked to format a name to the | ||||
| 	same format string again we can be as quick as possible. | ||||
|         This method constructs a new function that is specifically written  | ||||
|         to format a name given a particualar format string. This is worthwhile | ||||
|         because the format string itself rarely changes, so by caching the new | ||||
|         function and calling it directly when asked to format a name to the | ||||
|         same format string again we can be as quick as possible. | ||||
|  | ||||
| 	The new function is of the form: | ||||
|         The new function is of the form: | ||||
|  | ||||
| 	def fn(raw_data): | ||||
|         def fn(raw_data): | ||||
|             return "%s %s %s %s %s" % (raw_data[_TITLE], | ||||
|                    raw_data[_FIRSTNAME], | ||||
|                    raw_data[_PREFIX], | ||||
| @@ -264,15 +265,15 @@ class NameDisplay: | ||||
|  | ||||
|         """ | ||||
|  | ||||
| 	# we need the names of each of the variables or methods that are | ||||
| 	# called to fill in each format flag. | ||||
|         # we need the names of each of the variables or methods that are | ||||
|         # called to fill in each format flag. | ||||
|         d = {"%t":"raw_data[_TITLE]", | ||||
|              "%f":"raw_data[_FIRSTNAME]", | ||||
|              "%p":"raw_data[_PREFIX]", | ||||
|              "%l":"raw_data[_SURNAME]", | ||||
|              "%s":"raw_data[_SUFFIX]", | ||||
|              "%y":"raw_data[_PATRONYM]", | ||||
| 	     "%c":"raw_data[_CALL]", | ||||
|              "%c":"raw_data[_CALL]", | ||||
|              "%T":"raw_data[_TITLE].upper()", | ||||
|              "%F":"raw_data[_FIRSTNAME].upper()", | ||||
|              "%P":"raw_data[_PREFIX].upper()", | ||||
| @@ -284,8 +285,8 @@ class NameDisplay: | ||||
|  | ||||
|         new_fmt = format_str | ||||
|  | ||||
| 	# replace the specific format string flags with a  | ||||
| 	# flag that works in standard python format strings. | ||||
|         # replace the specific format string flags with a  | ||||
|         # flag that works in standard python format strings. | ||||
|         new_fmt = new_fmt.replace("%t","%s") | ||||
|         new_fmt = new_fmt.replace("%f","%s") | ||||
|         new_fmt = new_fmt.replace("%p","%s") | ||||
| @@ -303,10 +304,10 @@ class NameDisplay: | ||||
|         new_fmt = new_fmt.replace("%C","%s") | ||||
|         new_fmt = new_fmt.replace("%%",'%') | ||||
|  | ||||
| 	# find each format flag in the original format string | ||||
| 	# for each one we find the variable name that is needed to  | ||||
| 	# replace it and add this to a list. This list will be used | ||||
| 	# generate the replacement tuple. | ||||
|         # find each format flag in the original format string | ||||
|         # for each one we find the variable name that is needed to  | ||||
|         # replace it and add this to a list. This list will be used | ||||
|         # generate the replacement tuple. | ||||
|         pat = re.compile("%.") | ||||
|  | ||||
|         param = () | ||||
| @@ -317,37 +318,37 @@ class NameDisplay: | ||||
|  | ||||
|         s = 'def fn(raw_data):\n'\ | ||||
|             ' return "%s" %% (%s)' % (new_fmt,",".join(param)) | ||||
| 	exec(s) | ||||
|         exec(s) | ||||
|  | ||||
|         return fn | ||||
|  | ||||
|     def _gen_cooked_func(self, format_str): | ||||
| 	"""The job of building the name from a format string is rather | ||||
| 	expensive and it is called lots and lots of times. So it is worth | ||||
| 	going to some length to optimise it as much as possible.  | ||||
|         """The job of building the name from a format string is rather | ||||
|         expensive and it is called lots and lots of times. So it is worth | ||||
|         going to some length to optimise it as much as possible.  | ||||
|  | ||||
| 	This method constructs a new function that is specifically written  | ||||
| 	to format a name given a particualar format string. This is worthwhile | ||||
| 	because the format string itself rarely changes, so by caching the new | ||||
| 	function and calling it directly when asked to format a name to the | ||||
| 	same format string again we can be as quick as possible. | ||||
|         This method constructs a new function that is specifically written  | ||||
|         to format a name given a particualar format string. This is worthwhile | ||||
|         because the format string itself rarely changes, so by caching the new | ||||
|         function and calling it directly when asked to format a name to the | ||||
|         same format string again we can be as quick as possible. | ||||
|  | ||||
| 	The new function is of the form: | ||||
|         The new function is of the form: | ||||
|  | ||||
| 	def fn(first,surname,prefix,suffix,patronymic,title,call,): | ||||
|         def fn(first,surname,prefix,suffix,patronymic,title,call,): | ||||
|             return "%s %s %s %s %s" % (first,surname,prefix,suffix,patronymic) | ||||
|  | ||||
|         """ | ||||
|  | ||||
| 	# we need the names of each of the variables or methods that are | ||||
| 	# called to fill in each format flag. | ||||
|         # we need the names of each of the variables or methods that are | ||||
|         # called to fill in each format flag. | ||||
|         d = {"%t":"title", | ||||
|              "%f":"first", | ||||
|              "%p":"prefix", | ||||
|              "%l":"surname", | ||||
|              "%s":"suffix", | ||||
|              "%y":"patronymic", | ||||
| 	     "%c":"call", | ||||
|              "%c":"call", | ||||
|              "%T":"title.upper()", | ||||
|              "%F":"first.upper()", | ||||
|              "%P":"prefix.upper()", | ||||
| @@ -360,8 +361,8 @@ class NameDisplay: | ||||
|  | ||||
|         new_fmt = format_str | ||||
|  | ||||
| 	# replace the specific format string flags with a  | ||||
| 	# flag that works in standard python format strings. | ||||
|         # replace the specific format string flags with a  | ||||
|         # flag that works in standard python format strings. | ||||
|         new_fmt = new_fmt.replace("%t","%s") | ||||
|         new_fmt = new_fmt.replace("%f","%s") | ||||
|         new_fmt = new_fmt.replace("%p","%s") | ||||
| @@ -379,11 +380,11 @@ class NameDisplay: | ||||
|         new_fmt = new_fmt.replace("%C","%s") | ||||
|         new_fmt = new_fmt.replace("%%",'%') | ||||
|  | ||||
| 	# find each format flag in the original format string | ||||
| 	# for each one we find the variable name that is needed to  | ||||
| 	# replace it and add this to a list. This list will be used | ||||
| 	# generate the replacement tuple. | ||||
|         pat = re.compile("%.") | ||||
|         # find each format flag in the original format string | ||||
|         # for each one we find the variable name that is needed to  | ||||
|         # replace it and add this to a list. This list will be used | ||||
|         # generate the replacement tuple. | ||||
|         pat = re.compile('|'.join(d.keys())) | ||||
|  | ||||
|         param = () | ||||
|         mat = pat.search(format_str) | ||||
| @@ -393,7 +394,7 @@ class NameDisplay: | ||||
|  | ||||
|         s = 'def fn(first,surname,prefix,suffix,patronymic,title,call,):\n'\ | ||||
|             ' return "%s" %% (%s)' % (new_fmt,",".join(param)) | ||||
| 	exec(s) | ||||
|         exec(s) | ||||
|  | ||||
|         return fn | ||||
|  | ||||
| @@ -403,19 +404,19 @@ class NameDisplay: | ||||
|                                      name.call,format_str) | ||||
|  | ||||
|     def format_str_raw(self,raw_data,format_str): | ||||
| 	""" | ||||
| 	Format a name from the raw name list. To make this as fast as possible | ||||
| 	this uses _gen_raw_func to generate a new method for each new format_string. | ||||
| 	 | ||||
| 	Is does not call _format_str_base because it would introduce an extra  | ||||
| 	method call and we need all the speed we can squeeze out of this. | ||||
| 	""" | ||||
|         """ | ||||
|         Format a name from the raw name list. To make this as fast as possible | ||||
|         this uses _gen_raw_func to generate a new method for each new format_string. | ||||
|          | ||||
|         Is does not call _format_str_base because it would introduce an extra  | ||||
|         method call and we need all the speed we can squeeze out of this. | ||||
|         """ | ||||
|         func = self.__class__.raw_format_funcs.get(format_str) | ||||
|         if func == None: | ||||
|             func = self._gen_raw_func(format_str) | ||||
|             self.__class__.raw_format_funcs[format_str] = func | ||||
|  | ||||
| 	s = func(raw_data) | ||||
|         s = func(raw_data) | ||||
|         return ' '.join(s.split()) | ||||
|  | ||||
|  | ||||
| @@ -443,10 +444,14 @@ class NameDisplay: | ||||
|             func = self._gen_cooked_func(format_str) | ||||
|             self.__class__.format_funcs[format_str] = func | ||||
|  | ||||
| 	s = func(first,surname,prefix,suffix,patronymic,title,call) | ||||
|         try: | ||||
|             s = func(first,surname,prefix,suffix,patronymic,title,call) | ||||
|         except (ValueError,TypeError,): | ||||
|             raise NameDisplayError, "Incomplete format string" | ||||
|  | ||||
|         return ' '.join(s.split()) | ||||
|      | ||||
|     #-------------------------------------------------------------------------     | ||||
|     #------------------------------------------------------------------------- | ||||
|  | ||||
|     def sort_string(self,name): | ||||
|         return u"%-25s%-30s%s" % (name.surname,name.first_name,name.suffix) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # | ||||
| # Gramps - a GTK+/GNOME based genealogy program | ||||
| # | ||||
| # Copyright (C) 2000-2006  Donald N. Allingham | ||||
| # Copyright (C) 2000-2007  Donald N. Allingham | ||||
| # | ||||
| # 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 | ||||
| @@ -383,8 +383,6 @@ class EditFamily(EditPrimary): | ||||
|         EditPrimary.__init__(self, dbstate, uistate, track, | ||||
|                              family, dbstate.db.get_family_from_handle) | ||||
|  | ||||
|         self.in_save = False | ||||
|  | ||||
|         # look for the scenerio of a child and no parents on a new | ||||
|         # family | ||||
|          | ||||
| @@ -433,7 +431,7 @@ class EditFamily(EditPrimary): | ||||
|     def check_for_family_change(self, handles): | ||||
|  | ||||
|         # check to see if the handle matches the current object | ||||
|         if not self.in_save and self.obj.get_handle() in handles: | ||||
|         if self.obj.get_handle() in handles: | ||||
|  | ||||
|             self.obj = self.dbstate.db.get_family_from_handle(self.obj.get_handle()) | ||||
|             self.reload_people() | ||||
| @@ -802,7 +800,6 @@ class EditFamily(EditPrimary): | ||||
|  | ||||
|     def __do_save(self): | ||||
|         self.ok_button.set_sensitive(False) | ||||
|         self.in_save = True | ||||
|  | ||||
|         if not self.added: | ||||
|             original = self.db.get_family_from_handle(self.obj.handle) | ||||
| @@ -834,7 +831,21 @@ class EditFamily(EditPrimary): | ||||
|             self.ok_button.set_sensitive(True) | ||||
|             return | ||||
|  | ||||
|         if not original and self.object_is_empty(): | ||||
|             QuestionDialog.ErrorDialog( | ||||
|                 _("Cannot save family"), | ||||
|                 _("No data exists for this family. " | ||||
|                   "Please enter data or cancel the edit.")) | ||||
|             self.ok_button.set_sensitive(True) | ||||
|             return | ||||
|  | ||||
|         # We disconnect the callbacks to all signals we connected earlier. | ||||
|         # This prevents the signals originating in any of the following | ||||
|         # commits from being caught by us again. | ||||
|         for key in self.signal_keys: | ||||
|             self.db.disconnect(key) | ||||
|         self.signal_keys = [] | ||||
|              | ||||
|         if not original and not self.object_is_empty(): | ||||
|             trans = self.db.transaction_begin() | ||||
|  | ||||
| @@ -861,12 +872,6 @@ class EditFamily(EditPrimary): | ||||
|  | ||||
|             self.db.add_family(self.obj,trans) | ||||
|             self.db.transaction_commit(trans,_("Add Family")) | ||||
|         elif not original and self.object_is_empty(): | ||||
|             QuestionDialog.ErrorDialog(_("Cannot save family"), | ||||
|                                        _("No data exists for this family. Please " | ||||
|                                          "enter data or cancel the edit.")) | ||||
|             self.ok_button.set_sensitive(True) | ||||
|             return | ||||
|         elif original and self.object_is_empty(): | ||||
|             trans = self.db.transaction_begin() | ||||
|             self.db.remove_family(self.obj.handle,trans) | ||||
| @@ -901,7 +906,6 @@ class EditFamily(EditPrimary): | ||||
|                 self.db.commit_family(self.obj,trans) | ||||
|             self.db.transaction_commit(trans,_("Edit Family")) | ||||
|  | ||||
|         self.in_save = False | ||||
|         self.close() | ||||
|  | ||||
|     def _cleanup_on_exit(self): | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # | ||||
| # Gramps - a GTK+/GNOME based genealogy program | ||||
| # | ||||
| # Copyright (C) 2003-2006  Donald N. Allingham | ||||
| # Copyright (C) 2003-2007  Donald N. Allingham | ||||
| # | ||||
| # 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 | ||||
| @@ -151,3 +151,14 @@ class DbError(Exception): | ||||
|     def __str__(self): | ||||
|         "Return string representation" | ||||
|         return self.value | ||||
|  | ||||
| class NameDisplayError(Exception): | ||||
|     """ | ||||
|     Error used to report that the name display format string is invalid. | ||||
|     """ | ||||
|     def __init__(self,value): | ||||
|         Exception.__init__(self) | ||||
|         self.value = value | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.value | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
| # | ||||
| #------------------------------------------------------------------------- | ||||
| from gettext import gettext as _ | ||||
| from xml.sax.saxutils import escape | ||||
|  | ||||
| #------------------------------------------------------------------------- | ||||
| # | ||||
| @@ -46,6 +47,7 @@ from RelLib import Name | ||||
| import ManagedWindow | ||||
| from GrampsWidgets import * | ||||
| import QuestionDialog | ||||
| from Errors import NameDisplayError | ||||
|  | ||||
| #------------------------------------------------------------------------- | ||||
| # | ||||
| @@ -379,12 +381,12 @@ class GrampsPreferences(ManagedWindow.ManagedWindow): | ||||
|         Name format editor Edit button callback | ||||
|         """ | ||||
|         num,name,fmt = self.selected_fmt[COL_NUM:COL_EXPL] | ||||
|         dlg = NameFormatEditDlg(name,fmt,self.examplename) | ||||
|         dlg = NameFormatEditDlg(name, fmt, self.examplename) | ||||
|         dlg.dlg.set_transient_for(self.window) | ||||
|         (res,name,fmt) = dlg.run() | ||||
|  | ||||
|         if name != self.selected_fmt[COL_NAME] or \ | ||||
|            fmt != self.selected_fmt[COL_FMT]: | ||||
|         if res == gtk.RESPONSE_OK and (name != self.selected_fmt[COL_NAME] or  | ||||
|                                        fmt != self.selected_fmt[COL_FMT]): | ||||
|             exmpl = _nd.format_str(self.examplename,fmt) | ||||
|             self.fmt_model.set(self.iter,COL_NAME,name, | ||||
|                                COL_FMT,fmt, | ||||
| @@ -586,12 +588,13 @@ class NameFormatEditDlg: | ||||
|     """ | ||||
|     """ | ||||
|      | ||||
|     def __init__(self,fmt_name,fmt_str,name): | ||||
|     def __init__(self, fmt_name, fmt_str, name): | ||||
|         self.fmt_name = fmt_name | ||||
|         self.fmt_str = fmt_str | ||||
|         self.name = name | ||||
|         self.valid = True | ||||
|  | ||||
|         self.top = gtk.glade.XML(const.gladeFile,'namefmt_edit','gramps') | ||||
|         self.top = gtk.glade.XML(const.gladeFile, 'namefmt_edit','gramps') | ||||
|         self.dlg = self.top.get_widget('namefmt_edit') | ||||
|         ManagedWindow.set_titles(self.dlg, None, _('Name Format Editor')) | ||||
|          | ||||
| @@ -601,7 +604,7 @@ class NameFormatEditDlg: | ||||
|         self.nameentry.set_text(self.fmt_name) | ||||
|          | ||||
|         self.formatentry = self.top.get_widget('format_entry') | ||||
|         self.formatentry.connect('changed',self.cb_format_changed) | ||||
|         self.formatentry.connect('changed', self.cb_format_changed) | ||||
|         self.formatentry.set_text(self.fmt_str) | ||||
|          | ||||
|     def run(self): | ||||
| @@ -614,7 +617,15 @@ class NameFormatEditDlg: | ||||
|             self.fmt_str = self.formatentry.get_text() | ||||
|              | ||||
|             if self.response == gtk.RESPONSE_OK: | ||||
|                 if self.fmt_name == '' and self.fmt_str == '': | ||||
|                 if not self.valid: | ||||
|                     q = QuestionDialog.QuestionDialog2( | ||||
|                         _('The format definition is invalid'), | ||||
|                         _('What would you like to do?'), | ||||
|                         _('_Continue anyway'), _('_Modify format'), | ||||
|                         parent=self.dlg) | ||||
|                     running = not q.run() | ||||
|                     self.response = gtk.RESPONSE_CANCEL | ||||
|                 elif self.fmt_name == '' and self.fmt_str == '': | ||||
|                     self.response = gtk.RESPONSE_CANCEL | ||||
|                 elif (self.fmt_name == '') ^ (self.fmt_str == ''): | ||||
|                     QuestionDialog.ErrorDialog( | ||||
| @@ -625,11 +636,15 @@ class NameFormatEditDlg: | ||||
|         self.dlg.destroy() | ||||
|         return (self.response, self.fmt_name, self.fmt_str) | ||||
|  | ||||
|     def cb_format_changed(self,obj): | ||||
|     def cb_format_changed(self, obj): | ||||
|         try: | ||||
|             t = (_nd.format_str(self.name,obj.get_text())) | ||||
|         except ValueError, msg: | ||||
|             t = _("Invalid format string: %s") % msg | ||||
|         self.examplelabel.set_text( | ||||
|             '<span weight="bold" style="italic">%s</span>' % t) | ||||
|             t = (_nd.format_str(self.name, escape(obj.get_text()))) | ||||
|             sample = '<span weight="bold" style="italic">%s</span>' % t | ||||
|             self.valid = True | ||||
|         except NameDisplayError: | ||||
|             t = _("Invalid or incomplete format definition") | ||||
|             sample = '<span foreground="#FF0000">%s</span>' % t | ||||
|             self.valid = False | ||||
|  | ||||
|         self.examplelabel.set_text(sample) | ||||
|         self.examplelabel.set_use_markup(True) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user