diff --git a/src/Config/_GrampsConfigKeys.py b/src/Config/_GrampsConfigKeys.py index e2d422845..6207e3ba4 100644 --- a/src/Config/_GrampsConfigKeys.py +++ b/src/Config/_GrampsConfigKeys.py @@ -82,6 +82,8 @@ NOTE_HEIGHT = ('interface', 'note-height', 1) NOTE_WIDTH = ('interface', 'note-width', 1) PERSON_HEIGHT = ('interface', 'person-height', 1) PERSON_WIDTH = ('interface', 'person-width', 1) +PREFIX_SUFFIX = ('interface', 'prefix-suffix', 1) +PATRO_TITLE = ('interface', 'patro-title', 1) EVENT_HEIGHT = ('interface', 'event-height', 1) EVENT_WIDTH = ('interface', 'event-width', 1) EVENT_REF_HEIGHT = ('interface', 'event-ref-height', 1) @@ -211,6 +213,8 @@ default_value = { NOTE_WIDTH : 700, PERSON_HEIGHT : 550, PERSON_WIDTH : 750, + PREFIX_SUFFIX : 0, + PATRO_TITLE : 0, EVENT_HEIGHT : 450, EVENT_WIDTH : 600, EVENT_REF_HEIGHT : 450, diff --git a/src/Editors/_EditPerson.py b/src/Editors/_EditPerson.py index 8c44fffb4..f3efb8168 100644 --- a/src/Editors/_EditPerson.py +++ b/src/Editors/_EditPerson.py @@ -76,10 +76,6 @@ _select_gender = ((True, False, False), (False, True, False), (False, False, True)) -_use_patronymic = set( - ["ru", "RU", "ru_RU", "koi8r", "ru_koi8r", "russian", "Russian"] - ) - class EditPerson(EditPrimary): """ The EditPerson dialog is derived from the EditPrimary class. @@ -88,7 +84,6 @@ class EditPerson(EditPrimary): """ - use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic QR_CATEGORY = CATEGORY_QR_PERSON def __init__(self, dbstate, uistate, track, person, callback=None): @@ -114,9 +109,13 @@ class EditPerson(EditPrimary): def get_menu_title(self): if self.obj.get_handle(): name = name_displayer.display(self.obj) - title = _('Person') + ': %s' % name + title = _('Person: %(name)s') % {'name': name} else: - title = _('New Person') + name = name_displayer.display(self.obj) + if name: + title = _('New Person: %(name)s') % {'name': name} + else: + title = _('New Person') return title def _local_init(self): @@ -255,28 +254,23 @@ class EditPerson(EditPrimary): self.db.readonly, self.db.get_name_types()) - if self.use_patronymic: - self.prefix = widgets.MonitoredEntry( - self.top.get_widget("prefix"), - self.pname.set_patronymic, - self.pname.get_patronymic, - self.db.readonly) - - prefix_label = self.top.get_widget('prefix_label') - prefix_label.set_text(_('Patronymic:')) - prefix_label.set_use_underline(True) - else: - self.prefix = widgets.MonitoredEntry( - self.top.get_widget("prefix"), - self.pname.set_surname_prefix, - self.pname.get_surname_prefix, - self.db.readonly) - - self.suffix = widgets.MonitoredEntry( - self.top.get_widget("suffix"), - self.pname.set_suffix, - self.pname.get_suffix, - self.db.readonly) + self.prefix_suffix = widgets.MonitoredComboSelectedEntry( + self.top.get_widget("prefixcmb"), + self.top.get_widget("prefixentry"), + [_('Prefix'), _('Suffix')], + [self.pname.set_surname_prefix, self.pname.set_suffix], + [self.pname.get_surname_prefix, self.pname.get_suffix], + default = Config.get(Config.PREFIX_SUFFIX), + read_only = self.db.readonly) + + self.patro_title = widgets.MonitoredComboSelectedEntry( + self.top.get_widget("patrocmb"), + self.top.get_widget("patroentry"), + [_('Patronymic'), _('Title')], + [self.pname.set_patronymic, self.pname.set_title], + [self.pname.get_patronymic, self.pname.get_title], + default = Config.get(Config.PATRO_TITLE), + read_only = self.db.readonly) self.call = widgets.MonitoredEntry( self.top.get_widget("call"), @@ -290,12 +284,6 @@ class EditPerson(EditPrimary): self.pname.get_first_name, self.db.readonly) - self.title = widgets.MonitoredEntry( - self.top.get_widget("title"), - self.pname.set_title, - self.pname.get_title, - self.db.readonly) - self.surname_field = widgets.MonitoredEntry( self.top.get_widget("surname"), self.pname.set_surname, @@ -309,6 +297,15 @@ class EditPerson(EditPrimary): self.obj.get_gramps_id, self.db.readonly) + #make sure title updates automatically + for obj in [self.top.get_widget("surname"), + self.top.get_widget("given_name"), + self.top.get_widget("patroentry"), + self.top.get_widget("call"), + self.top.get_widget("prefixentry"), + ]: + obj.connect('changed', self._changed_title) + def _create_tabbed_pages(self): """ Create the notebook tabs and insert them into the main window. @@ -376,23 +373,26 @@ class EditPerson(EditPrimary): notebook.show_all() self.top.get_widget('vbox').pack_start(notebook, True) + def _changed_title(self, obj): + """ + callback to changes typed by user to the person name. + Update the window title + """ + self.update_title(self.get_menu_title()) + def name_callback(self): + """ + Callback if changes happen in the name tab. + The Preferred Name is _NOT_ part of the name tab, but name tab allows + reorder and hence setting of new primary name. + """ self.pname = self.obj.get_primary_name() self.ntype_field.reinit(self.pname.set_type, self.pname.get_type) - if self.use_patronymic: - self.prefix.reinit( - self.pname.set_patronymic, - self.pname.get_patronymic) - else: - self.prefix.reinit( - self.pname.set_surname_prefix, - self.pname.get_surname_prefix) - - self.suffix.reinit( - self.pname.set_suffix, - self.pname.get_suffix) + self.prefix_suffix.reinit( + [self.pname.set_surname_prefix, self.pname.set_suffix], + [self.pname.get_surname_prefix, self.pname.get_suffix]) self.call.reinit( self.pname.set_call_name, @@ -402,9 +402,9 @@ class EditPerson(EditPrimary): self.pname.set_first_name, self.pname.get_first_name) - self.title.reinit( - self.pname.set_title, - self.pname.get_title) + self.patro_title.reinit( + [self.pname.set_patronymic, self.pname.set_title], + [self.pname.get_patronymic, self.pname.get_title]) self.surname_field.reinit( self.pname.set_surname, @@ -740,7 +740,7 @@ class EditPerson(EditPrimary): This allows us to update the main form in response to any changes. """ - for obj in (self.suffix, self.prefix, self.given, self.title, + for obj in (self.prefix_suffix, self.patro_title, self.given, self.ntype_field, self.surname_field, self.call): obj.update() @@ -855,6 +855,8 @@ class EditPerson(EditPrimary): (width, height) = self.window.get_size() Config.set(Config.PERSON_WIDTH, width) Config.set(Config.PERSON_HEIGHT, height) + Config.set(Config.PREFIX_SUFFIX, self.prefix_suffix.active_key) + Config.set(Config.PATRO_TITLE, self.patro_title.active_key) Config.sync() diff --git a/src/ManagedWindow.py b/src/ManagedWindow.py index 89791fc9e..9349e0411 100644 --- a/src/ManagedWindow.py +++ b/src/ManagedWindow.py @@ -379,6 +379,8 @@ class ManagedWindow: """ self.isWindow = isWindow + self.msg = msg + self.titlelabel = title if self.isWindow : set_titles(self, title, text, msg) else : @@ -386,6 +388,12 @@ class ManagedWindow: #closing the gtk.Window must also close ManagedWindow self.window = window self.window.connect('delete-event', self.close) + + def update_title(self, text): + if self.isWindow: + set_titles(self, self.titlelabel, text, self.msg) + else: + set_titles(self.window, self.titlelabel, text, self.msg) def build_menu_names(self, obj): return ('Undefined Menu','Undefined Submenu') diff --git a/src/glade/edit_person.glade b/src/glade/edit_person.glade index 0ea33ed47..15eef03a3 100644 --- a/src/glade/edit_person.glade +++ b/src/glade/edit_person.glade @@ -159,87 +159,6 @@ - - - True - _Prefix: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0.5 - 0 - 0 - prefix - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 5 - 6 - 1 - 2 - fill - - - - - - - True - Tit_le: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0.5 - 0 - 0 - title - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 1 - 2 - 3 - 4 - fill - - - - - - - True - A title used to refer to the person, such as "Dr." or "Rev." - True - True - True - 0 - - True - * - False - 13 - - - 2 - 3 - 3 - 4 - - - - True @@ -253,7 +172,7 @@ 0.5 0 0 - gender + gender PANGO_ELLIPSIZE_NONE -1 False @@ -272,6 +191,7 @@ True + part of a person's name indicating the family to which the person belongs True True True @@ -290,116 +210,6 @@ - - - True - S_uffix: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0.5 - 0 - 0 - suffix - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 3 - 4 - 3 - 4 - fill - - - - - - - True - _ID: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - gid - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 3 - 4 - 5 - 6 - fill - - - - - - - True - _Type: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0.5 - 0 - 0 - ntype - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 5 - 6 - 3 - 4 - fill - - - - - - - True - An optional suffix to the name, such as "Jr." or "III" - True - True - True - 0 - - True - * - False - 6 - - - 4 - 5 - 3 - 4 - - - - True @@ -411,7 +221,7 @@ True * False - 12 + 7 4 @@ -422,23 +232,6 @@ - - - True - False - True - True - - - 6 - 7 - 3 - 4 - fill - - - - True @@ -467,34 +260,6 @@ - - - True - <b>Preferred name</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 7 - 0 - 1 - fill - - - - 124 @@ -569,7 +334,7 @@ 0.5 0 0 - marker + marker PANGO_ELLIPSIZE_NONE -1 False @@ -598,7 +363,7 @@ 0.5 0 0 - call + call PANGO_ELLIPSIZE_NONE -1 False @@ -614,71 +379,6 @@ - - - True - False - 6 - - - - True - An optional prefix for the family name that is not used in sorting, such as "de" or "van" - True - True - True - 0 - - True - * - False - 10 - - - 0 - True - True - - - - - - True - Edit the preferred name - True - GTK_RELIEF_NORMAL - True - - - - - True - gtk-edit - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - 6 - 7 - 1 - 2 - fill - fill - - - True @@ -706,6 +406,7 @@ True + Part of the Given name that is the normally used name. True True True @@ -724,25 +425,6 @@ - - - True - Female -Male -Unknown - False - True - - - 2 - 3 - 5 - 6 - fill - - - - True @@ -801,6 +483,363 @@ Unknown fill + + + + True + False + 0 + + + + True + <b>Preferred name</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + <b> - </b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Edit the preferred name + True + GTK_RELIEF_NORMAL + True + + + + + True + gtk-edit + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + 4 + 0 + 1 + fill + fill + + + + + + True + _Type: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + ntype + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 5 + 6 + 1 + 2 + fill + + + + + + + True + False + True + True + + + 6 + 7 + 1 + 2 + fill + fill + + + + + + True + Prefix: An optional prefix for the family name that is not used in sorting, such as "de" or "van" +Suffix: An optional suffix to the name, such as "Jr." or "III" + True + True + True + 0 + + True + * + False + 6 + + + 2 + 3 + 3 + 4 + fill + + + + + + + True + False + 12 + + + + True + Female +Male +Unknown + False + True + + + 0 + True + True + + + + + + True + _ID: + True + False + GTK_JUSTIFY_RIGHT + False + False + 0 + 0.5 + 0 + 0 + gid + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 2 + 4 + 5 + 6 + fill + fill + + + + + + True + Patronimic: component of a personal name based on the name of one's father, grandfather, .... +Title: A title used to refer to the person, such as 'Dr.' or 'Rev.' + True + True + True + 0 + + True + * + False + + + 4 + 5 + 3 + 4 + + + + + + + True + False + 0 + + + + True + False + True + + + 0 + True + True + + + + + + True + : + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + prefixentry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 1 + 2 + 3 + 4 + fill + fill + + + + + + True + False + 0 + + + + True + + False + True + + + 0 + True + True + + + + + + True + : + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + patroentry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 3 + 4 + 3 + 4 + fill + fill + + diff --git a/src/widgets/monitoredwidgets.py b/src/widgets/monitoredwidgets.py index 91d704bf5..120733294 100644 --- a/src/widgets/monitoredwidgets.py +++ b/src/widgets/monitoredwidgets.py @@ -22,7 +22,8 @@ __all__ = ["MonitoredCheckbox", "MonitoredEntry", "MonitoredSpinButton", "MonitoredText", "MonitoredType", "MonitoredDataType", - "MonitoredMenu", "MonitoredStrMenu", "MonitoredDate"] + "MonitoredMenu", "MonitoredStrMenu", "MonitoredDate", + "MonitoredComboSelectedEntry"] #------------------------------------------------------------------------- # @@ -31,6 +32,7 @@ __all__ = ["MonitoredCheckbox", "MonitoredEntry", "MonitoredSpinButton", #------------------------------------------------------------------------- import logging _LOG = logging.getLogger(".widgets.monitoredwidgets") +import locale #------------------------------------------------------------------------- # @@ -479,3 +481,119 @@ class MonitoredDate: field.set_editable(not readonly) button.set_sensitive(not readonly) +#------------------------------------------------------------------------- +# +# MonitoredComboSelectedEntry class +# +#------------------------------------------------------------------------- +class MonitoredComboSelectedEntry: + """ + A MonitoredEntry driven by a Combobox to select what the entry field + works upon + """ + def __init__(self, objcombo, objentry, textlist, set_val_list, + get_val_list, default=0, read_only=False): + """ + Create a MonitoredComboSelectedEntry + Objcombo and objentry should be the gtk widgets to use + textlist is the values that must be used in the combobox + Every value needs an entry in set/get_val_list with the data retrieval + and storage method of the data entered in the entry box + Read_only should be true if no changes may be done + default is the entry in the combobox that must be preselected + """ + self.objcombo = objcombo + self.objentry = objentry + self.set_val_list = set_val_list + self.get_val_list = get_val_list + + #fill the combobox, set on a specific entry + self.mapping = dict([[i,x] for (i,x) in zip(range(len(textlist)), + textlist)]) + + self.active_key = default + self.active_index = 0 + + self.__fill() + self.objcombo.clear() + self.objcombo.set_model(self.store) + cell = gtk.CellRendererText() + self.objcombo.pack_start(cell, True) + self.objcombo.add_attribute(cell, 'text', 1) + self.objcombo.set_active(self.active_index) + self.objcombo.connect('changed', self.on_combochange) + + #fill the entrybox with required data + self.entry_reinit() + self.objentry.connect('changed', self._on_change_entry) + + #set correct editable + self.enable(not read_only) + + def __fill(self): + """ + Fill combo with data + """ + self.store = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING) + keys = self.mapping.keys() + keys.sort(self.__by_value) + index = 0 + for key in keys: + self.store.append(row=[key, self.mapping[key]]) + if key == self.active_key: + self.active_index = index + index = index + 1 + + def __by_value(self, first, second): + """ + Method for sorting keys based on the values. + """ + fvalue = self.mapping[first] + svalue = self.mapping[second] + return locale.strcoll(fvalue, svalue) + + def on_combochange(self, obj): + """ + callback for change on the combo, change active iter, update + associated entrybox + """ + self.active_key = self.store.get_value(self.objcombo.get_active_iter(), + 0) + self.entry_reinit() + + def reinit(self, set_val_list, get_val_list): + """ + The interface is attached to another object, so the methods need to be + reset. + """ + self.set_val_list = set_val_list + self.get_val_list = get_val_list + self.update() + + def entry_reinit(self): + """ + Make the entry field show the value corresponding to the active key + """ + self.objentry.set_text(self.get_val_list[self.active_key]()) + self.set_val = self.set_val_list[self.active_key] + self.get_val = self.get_val_list[self.active_key] + + def _on_change_entry(self, obj): + """ + Callback when the entry field changes + """ + self.set_val_list[self.active_key](self.get_value_entry()) + + def get_value_entry(self): + return unicode(self.objentry.get_text()) + + def enable(self, value): + self.objentry.set_sensitive(value) + self.objentry.set_editable(value) + + def update(self): + """ + Method called when object changed without interface change + Eg: name editor save brings you back to person editor that must update + """ + self.entry_reinit()