diff --git a/ChangeLog b/ChangeLog index 46a5775f3..a67997060 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-01-06 Don Allingham + * src/Editors/_EditAddress.py: new date entry + * src/Editors/_EditLdsOrd.py: new date_entry + * src/Editors/_EditSourceRef.py: new date_entry + * src/Editors/_EditEventRef.py: new date_entry + * src/Editors/_EditMedia.py: new date_entry + * src/Editors/_EditName.py: new date_entry + * src/Editors/_EditEvent.py: new date_entry + * src/GrampsWidgets.py: add options to ValidatedDateEntry to specify colors and icon + * src/glade/gramps.glade: new date_entry + * src/Errors.py: new date_entry + * src/DateEdit.py: new date_entry + 2007-01-05 Richard Taylor * src/docgen/GtkPrint.py: minor tweeks diff --git a/src/DateEdit.py b/src/DateEdit.py index be5fdd8c2..3e6b7e44a 100644 --- a/src/DateEdit.py +++ b/src/DateEdit.py @@ -68,6 +68,7 @@ import DateHandler import const import GrampsDisplay import ManagedWindow +from Errors import MaskError, ValidationError #------------------------------------------------------------------------- # @@ -120,7 +121,7 @@ class DateEdit: self.pixmap_obj = button_obj.get_child() - self.text_obj.connect('focus-out-event',self.parse_and_check) + self.text_obj.connect('validate',self.validate) self.button_obj.connect('clicked',self.invoke_date_editor) self.text = unicode(self.text_obj.get_text()) @@ -131,31 +132,37 @@ class DateEdit: Check current date object and display LED indicating the validity. """ if self.date_obj.get_modifier() == Date.MOD_TEXTONLY: - self.pixmap_obj.set_from_pixbuf( - self.pixmap_obj.render_icon(gtk.STOCK_DIALOG_ERROR, - gtk.ICON_SIZE_MENU)) - elif self.date_obj.is_regular(): - self.pixmap_obj.set_from_pixbuf( - self.pixmap_obj.render_icon(gtk.STOCK_YES, - gtk.ICON_SIZE_MENU)) + self.text_obj.set_invalid() + return False else: - self.pixmap_obj.set_from_pixbuf( - self.pixmap_obj.render_icon(gtk.STOCK_DIALOG_WARNING, - gtk.ICON_SIZE_MENU)) - + self.text_obj.set_valid() + return True def parse_and_check(self,*obj): """ Called with the text box loses focus. Parses the text and calls the check() method ONLY if the text has changed. """ - text = unicode(self.text_obj.get_text()) if text != self.text: self.text = text self.date_obj.copy(DateHandler.parser.parse(text)) self.text_obj.set_text(DateHandler.displayer.display(self.date_obj)) - self.check() + if self.check(): + return None + else: + return ValidationError('Bad Date') + + def validate(self, widget, data): + """ + Called with the text box loses focus. Parses the text and calls + the check() method ONLY if the text has changed. + """ + self.date_obj.copy(DateHandler.parser.parse(unicode(data))) + if self.check(): + return None + else: + return ValidationError('Bad Date') def invoke_date_editor(self,obj): """ diff --git a/src/Editors/_EditAddress.py b/src/Editors/_EditAddress.py index 330606d8e..ff2632d69 100644 --- a/src/Editors/_EditAddress.py +++ b/src/Editors/_EditAddress.py @@ -80,8 +80,13 @@ class EditAddress(EditSecondary): _('Address Editor')) def _setup_fields(self): + table = self.top.get_widget('table26') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 1, 6, 0, 1) + self.addr_start = MonitoredDate( - self.top.get_widget("address_start"), + date_entry, self.top.get_widget("date_stat"), self.obj.get_date_object(), self.uistate, diff --git a/src/Editors/_EditEvent.py b/src/Editors/_EditEvent.py index 41afc5508..7a6ef4cd9 100644 --- a/src/Editors/_EditEvent.py +++ b/src/Editors/_EditEvent.py @@ -144,7 +144,11 @@ class EditEvent(EditPrimary): self.obj.get_type, custom_values=self.get_custom_events()) - date_entry = self.top.get_widget("eventDate") + table = self.top.get_widget('table21') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 3, 4, 0, 1) + self.date_field = MonitoredDate( date_entry, self.top.get_widget("date_stat"), diff --git a/src/Editors/_EditEventRef.py b/src/Editors/_EditEventRef.py index 756187e21..caba0618f 100644 --- a/src/Editors/_EditEventRef.py +++ b/src/Editors/_EditEventRef.py @@ -137,7 +137,11 @@ class EditEventRef(EditReference): self.db.readonly, custom_values=self.get_custom_events()) - date_entry = self.top.get_widget("eer_date") + table = self.top.get_widget('table62') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 1, 2, 1, 2) + self.date_check = MonitoredDate( date_entry, self.top.get_widget("eer_date_stat"), @@ -146,7 +150,6 @@ class EditEventRef(EditReference): self.track, self.db.readonly) - date_entry.grab_focus() def _create_tabbed_pages(self): """ diff --git a/src/Editors/_EditLdsOrd.py b/src/Editors/_EditLdsOrd.py index 71cbd942d..3fbfaab63 100644 --- a/src/Editors/_EditLdsOrd.py +++ b/src/Editors/_EditLdsOrd.py @@ -175,8 +175,13 @@ class EditLdsOrd(EditSecondary): self.top.get_widget("private"), self.obj, self.db.readonly) + table = self.top.get_widget('table') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 1, 2, 3, 4) + self.date_field = MonitoredDate( - self.top.get_widget("date"), + date_entry, self.top.get_widget("date_stat"), self.obj.get_date_object(), self.uistate, @@ -357,10 +362,15 @@ class EditFamilyLdsOrd(EditSecondary): self.priv = PrivacyButton( self.top.get_widget("private"), - self.obj) + self.obj, self.db.readonly) + + table = self.top.get_widget('table') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 1, 2, 3, 4) self.date_field = MonitoredDate( - self.top.get_widget("date"), + date_entry, self.top.get_widget("date_stat"), self.obj.get_date_object(), self.uistate, diff --git a/src/Editors/_EditMedia.py b/src/Editors/_EditMedia.py index 35c620e48..3c394594c 100644 --- a/src/Editors/_EditMedia.py +++ b/src/Editors/_EditMedia.py @@ -96,8 +96,13 @@ class EditMedia(EditPrimary): self.define_help_button(self.glade.get_widget('button102'),'adv-media') def _setup_fields(self): + table = self.glade.get_widget('table8') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 2, 3, 2, 3) + self.date_field = MonitoredDate( - self.glade.get_widget('date'), + date_entry, self.glade.get_widget("date_edit"), self.obj.get_date_object(), self.uistate, diff --git a/src/Editors/_EditName.py b/src/Editors/_EditName.py index 59ce98bd4..00f9b5342 100644 --- a/src/Editors/_EditName.py +++ b/src/Editors/_EditName.py @@ -159,9 +159,14 @@ class EditName(EditSecondary): self.obj.set_surname_prefix, self.obj.get_surname_prefix, self.db.readonly) - + + table = self.top.get_widget('table23') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 2, 3, 4, 5) + self.date = MonitoredDate( - self.top.get_widget("date"), + date_entry, self.top.get_widget("date_stat"), self.obj.get_date_object(), self.uistate, diff --git a/src/Editors/_EditSourceRef.py b/src/Editors/_EditSourceRef.py index 3240e22aa..5f6541de4 100644 --- a/src/Editors/_EditSourceRef.py +++ b/src/Editors/_EditSourceRef.py @@ -99,9 +99,13 @@ class EditSourceRef(EditReference): self.top.get_widget("private"), self.source, self.db.readonly) + print self.top.get_widget('title') + self.title = MonitoredEntry( - self.top.get_widget('title'), self.source.set_title, - self.source.get_title,self.db.readonly) + self.top.get_widget('title'), + self.source.set_title, + self.source.get_title, + self.db.readonly) self.abbrev = MonitoredEntry( self.top.get_widget('abbrev'), self.source.set_abbreviation, @@ -126,8 +130,13 @@ class EditSourceRef(EditReference): (_('Very High'), RelLib.SourceRef.CONF_VERY_HIGH)], self.db.readonly) + table = self.top.get_widget('table67') + date_entry = ValidatableMaskedEntry(str) + date_entry.show() + table.attach(date_entry, 1, 2, 0, 1) + self.date = MonitoredDate( - self.top.get_widget("date"), + date_entry, self.top.get_widget("date_stat"), self.source_ref.get_date_object(), self.uistate, diff --git a/src/Errors.py b/src/Errors.py index 2e9f68eea..3e7316793 100644 --- a/src/Errors.py +++ b/src/Errors.py @@ -128,3 +128,10 @@ class UnavailableError(Exception): def __str__(self): return self.value + +class MaskError(Exception): + pass + +class ValidationError(Exception): + pass + diff --git a/src/GrampsWidgets.py b/src/GrampsWidgets.py index eb0b42c23..700084b38 100644 --- a/src/GrampsWidgets.py +++ b/src/GrampsWidgets.py @@ -42,6 +42,8 @@ import const import Errors import Config +from Errors import MaskError, ValidationError + from DdTargets import DdTargets _lock_path = os.path.join(const.image_dir, 'stock_lock.png') @@ -662,12 +664,6 @@ class PlaceEntry: # #============================================================================ -class MaskError(Exception): - pass - -class ValidationError(Exception): - pass - class FadeOut(gobject.GObject): """I am a helper class to draw the fading effect of the background Call my methods start() and stop() to control the fading. @@ -686,10 +682,9 @@ class FadeOut(gobject.GObject): MERGE_COLORS_DELAY = 100 - ERROR_COLOR = "#ffd5d5" - - def __init__(self, widget): + def __init__(self, widget, err_color = "#ffd5d5"): gobject.GObject.__init__(self) + self.ERROR_COLOR = err_color self._widget = widget self._start_color = None self._background_timeout_id = -1 @@ -733,7 +728,7 @@ class FadeOut(gobject.GObject): ##self._log.debug('_start_merging: Starting') func = self._merge_colors(self._start_color, - gtk.gdk.color_parse(FadeOut.ERROR_COLOR)).next + gtk.gdk.color_parse(self.ERROR_COLOR)).next self._background_timeout_id = ( gobject.timeout_add(FadeOut.MERGE_COLORS_DELAY, func)) self._countdown_timeout_id = -1 @@ -2005,15 +2000,16 @@ class ValidatableMaskedEntry(MaskedEntry): #allowed_data_types = (basestring, datetime.date, datetime.time, #datetime.datetime, object) + number - def __init__(self, data_type=None): + def __init__(self, data_type=None, err_color = "#ffd5d5", error_icon=ERROR_ICON): self.data_type = None self.mandatory = False - + self.error_icon = error_icon + MaskedEntry.__init__(self) self._block_changed = False self._valid = True - self._fade = FadeOut(self) + self._fade = FadeOut(self, err_color) self._fade.connect('color-changed', self._on_fadeout__color_changed) # FIXME put data type support back @@ -2141,7 +2137,8 @@ class ValidatableMaskedEntry(MaskedEntry): self.set_tooltip(text) if not fade: - self.set_stock(ERROR_ICON) + if self.error_icon: + self.set_stock(self.error_icon) self.update_background(gtk.gdk.color_parse(self._fade.ERROR_COLOR)) return @@ -2150,7 +2147,8 @@ class ValidatableMaskedEntry(MaskedEntry): # (which removes this timeout) is called as soon as the user # types valid data. def done(fadeout, c): - self.set_stock(ERROR_ICON) + if self.error_icon: + self.set_stock(self.error_icon) self.queue_draw() fadeout.disconnect(c.signal_id) @@ -2245,7 +2243,7 @@ def main(args): label = gtk.Label('Mandatory masked entry validated against user function:') vbox.pack_start(label) - widget2 = ValidatableMaskedEntry(str) + widget2 = ValidatableMaskedEntry(str, "#e0e0e0", error_icon=None) widget2.set_mask('00/00/0000') widget2.connect('validate', on_validate) widget2.mandatory = True diff --git a/src/glade/gramps.glade b/src/glade/gramps.glade index f672bb569..e6787d44d 100644 --- a/src/glade/gramps.glade +++ b/src/glade/gramps.glade @@ -5544,7 +5544,6 @@ 0.5 0 0 - date PANGO_ELLIPSIZE_NONE -1 False @@ -5730,6 +5729,8 @@ True + 4 + stock_calendar 0.5 0.5 0 @@ -5747,27 +5748,6 @@ - - - True - True - True - True - 0 - - True - * - False - - - 2 - 3 - 2 - 3 - - - - True @@ -6843,7 +6823,6 @@ 0.5 0 0 - eventDate PANGO_ELLIPSIZE_NONE -1 False @@ -6871,6 +6850,8 @@ True + 4 + stock_calendar 0.5 0.5 0 @@ -6948,27 +6929,6 @@ - - - True - True - True - True - 0 - - True - * - False - - - 3 - 4 - 0 - 1 - - - - True @@ -8798,7 +8758,7 @@ 12 True 5 - 3 + 4 False 6 12 @@ -8969,62 +8929,48 @@ - + True - False - 0 - - - - True - True - True - True - 0 - - True - * - False - - - 0 - True - True - - - - - - True - Invoke date editor - True - GTK_RELIEF_NONE - True - - - - True - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - + + False + True 2 3 + 2 + 3 + fill + + + + + + True + Invoke date editor + True + GTK_RELIEF_NONE + True + + + + True + 4 + stock_calendar + 0.5 + 0.5 + 0 + 0 + + + + + 3 + 4 4 5 fill - fill + @@ -9076,29 +9022,13 @@ 2 - 3 + 4 1 2 fill fill - - - - True - - False - True - - - 2 - 3 - 2 - 3 - fill - - False @@ -10574,7 +10504,6 @@ 0.5 0 0 - eer_date PANGO_ELLIPSIZE_NONE -1 False @@ -10648,27 +10577,6 @@ - - - True - True - True - True - 0 - - True - * - False - - - 1 - 2 - 1 - 2 - - - - 6 @@ -10918,6 +10826,8 @@ True + 4 + stock_calendar 0.5 0.5 0 @@ -11198,7 +11108,6 @@ 0.5 0 0 - date PANGO_ELLIPSIZE_NONE -1 False @@ -11214,27 +11123,6 @@ - - - True - True - True - True - 0 - - True - * - False - - - 1 - 2 - 0 - 1 - - - - True @@ -11247,6 +11135,8 @@ True + 4 + stock_calendar 0.5 0.5 0 @@ -11697,27 +11587,6 @@ Very High - - - True - True - True - True - 0 - - True - * - False - - - 1 - 2 - 0 - 1 - - - - True @@ -11809,6 +11678,27 @@ Very High fill + + + + True + True + True + True + 0 + + True + + False + + + 1 + 2 + 0 + 1 + + + False @@ -12623,7 +12513,6 @@ Very High 0.5 0 0 - date PANGO_ELLIPSIZE_NONE -1 False @@ -12668,28 +12557,6 @@ Very High - - - True - True - True - True - True - 0 - - True - * - False - - - 1 - 2 - 3 - 4 - - - - True @@ -12700,6 +12567,8 @@ Very High True + 4 + stock_calendar 0.5 0.5 0 @@ -12773,24 +12642,6 @@ Very High - - - True - - - False - True - - - 1 - 2 - 0 - 1 - fill - fill - - - True @@ -13059,6 +12910,23 @@ Very High + + + + True + + + False + True + + + 1 + 2 + 0 + 1 + fill + + 0 @@ -13186,7 +13054,6 @@ Very High 0.5 0 0 - address_start PANGO_ELLIPSIZE_NONE -1 False @@ -13439,28 +13306,6 @@ Very High - - - True - True - True - True - True - 0 - - True - * - False - - - 1 - 6 - 0 - 1 - - - - True @@ -13565,6 +13410,8 @@ Very High True + 4 + stock_calendar 0.5 0.5 0