diff --git a/data/tests/imp_MediaTest.ged b/data/tests/imp_MediaTest.ged new file mode 100644 index 000000000..c52549ae2 --- /dev/null +++ b/data/tests/imp_MediaTest.ged @@ -0,0 +1,176 @@ +0 HEAD +1 SOUR Tester +2 VERS 1.0 +2 NAME The Tester +1 DATE 4 JUN 2016 +2 TIME 10:19:42 +1 FILE D:\Users\PRC\Documents\Family Tree Maker\Gramps Export raw.ged +1 COPR Copyright (c) 2016 The Tester. +1 GEDC +2 VERS 5.5.1 +2 FORM LINEAGE-LINKED +1 CHAR UTF-8 +1 LANG English +0 @I1@ INDI +1 NAME The /Tester/ +2 GIVN The +2 SURN Tester +1 OBJE +2 FORM jpeg +2 TITL Multimedia link embedded form v5.5 +2 FILE test_emb_55.jpg +2 NOTE @N0010@ +1 OBJE @M1@ +1 OBJE @M3@ +1 OBJE @M4@ +1 OBJE +2 FILE test_emb_551.jpg +3 FORM jpeg +4 MEDI photo +2 TITL Multimedia link embedded form v5.5.1 +2 NOTE @N0014@ +1 OBJE @M5@ +1 OBJE @M6@ +1 OBJE +2 FORM jpeg +2 TITL Multimedia link embedded form v5.5 2nd copy +2 FILE test_emb_55.jpg +2 NOTE @N0018@ +0 @M1@ OBJE +1 FORM jpeg +1 TITL Multimedia link to linked form v5.5 blob +1 BLOB +2 CONT .HM.......k.1..F.jwA.Dzzzzw............A....1.........0U.66..E.8 +2 CONT .......A..k.a6.A.......A..k.........../6....G.......0../..U..... +2 CONT .w1/m........HC0..../...zzzzzzzz..5zzk..AnA..U..W6U....2rRrRrRrR +2 CONT .Dw...............k.1.......1..A...5ykE/zzzx/.g//.Hxzk6/.Tzy/.k1 +2 CONT /Dw/.Tvz.E5zzUE9/kHz.Tw2/DzzzEEA.kE2zk5yzk2/zzs21.U2/Dw/.Tw/.Tzy +2 CONT /.fy/.HzzkHzzzo21Ds00.E2.UE2.U62/.k./Ds0.UE0/Do0..E8/UE2.U62.U9w +2 CONT /.Tx/.20.jg2/jo2..9u/.0U.6A.zk +1 OBJE @M2@ +1 REFN Ref12345M1 +2 TYPE SOMETEXT +1 NOTE @N0011@ +1 RIN ID09876M1 +1 CHAN +2 DATE 22 MAY 1987 +3 TIME 13:58:11 +0 @M2@ OBJE +1 FORM jpeg +1 TITL 2nd blob Multimedia link to linked form v5.5 blob +1 BLOB +2 CONT 67890gramps doesn't do this anyway, so don't bother doing it right. +0 @M3@ OBJE +1 FORM jpeg +1 TITL Multimedia link to linked form Gramps style v5.5ish file +1 FILE test.jpg +1 NOTE @N0012@ +1 CHAN +2 DATE 23 MAY 1987 +3 TIME 14:48:01 +0 @M4@ OBJE +1 FILE test.jpg +2 FORM jpeg +3 TYPE photo +2 TITL Multimedia link to linked form v5.5.1 file +1 REFN Ref1234567M4 +2 TYPE SOMETEXT +1 NOTE @N0013@ +1 SOUR A Great Photographer +2 TEXT who shall remain un-named +2 QUAY 0 +1 RIN ID098765M4 +1 CHAN +2 DATE 24 MAY 1987 +3 TIME 14:38:01 +0 @M5@ OBJE +1 FILE test.jpg +2 TITL Multimedia link to linked form FTM style file +2 DATE 6/4/2016 9:33:57 AM +2 TEXT A fine gentelman was he, upstanding in his community and a great +3 CONC believer in the testing of open source software. +1 NOTE @N0015@ +1 NOTE @N0016@ +0 @M6@ OBJE +1 FILE test.jpg +2 FORM jpeg +3 TYPE photo +2 TITL Multimedia link to linked form v5.5.1 with two files(1) +1 FILE test1.jpg +2 FORM jpeg +3 TYPE photo +2 TITL Multimedia link to linked form v5.5.1 with two files(2) +1 REFN Ref1234567M4 +2 TYPE SOMETEXT +1 NOTE @N0017@ +1 SOUR @S1@ +2 PAGE 77, 78 discussion of multimedia link with two files +2 DATA +3 DATE 7 JUN 2014 +3 TEXT A source who shall remain un-named +2 QUAY 0 +1 RIN ID098765M4 +1 CHAN +2 DATE 24 MAY 1987 +3 TIME 14:38:01 +0 @S1@ SOUR +1 AUTH The Tester +1 TITL The Testers personal files +1 PUBL Name: Tester Publishing Operations, Inc.; Location: OSF world +0 @N0010@ NOTE Media note test: Multimedia link embedded form v5.5 +1 CONT n OBJE {1:1} p.55 +1 CONT +1 FORM {1:1} p.48 +1 CONT +1 TITL {0:1} p.43 +1 CONT +1 FILE {1:1} p.47 +1 CONT +1 <> {0:M} p.33 +0 @N0011@ NOTE Media note test: Multimedia link to linked form v5.5 blob +1 CONT n @XREF:OBJE@ OBJE {1:1} +1 CONT +1 FORM {1:1} p.48 +1 CONT +1 TITL {0:1} p.43 +1 CONT +1 <> {0:M} p.33 +1 CONT +1 BLOB {1:1} +1 CONT +2 CONT {1:M} p.43 +1 CONT +1 OBJE @@ /* chain to continued object */ {0:1} p.26 +1 CONT +1 REFN {0:M} p.55 +1 CONT +2 TYPE {0:1} p.55 +1 CONT +1 RIN {0:1} p.38 +1 CONT +1 <> {0:1} p.29 +0 @N0012@ NOTE Media note test: Multimedia link to linked form Gramps style v5.5ish file +1 CONT n @XREF:OBJE@ OBJE {1:1} +1 CONT +1 FORM {1:1} p.48 +1 CONT +1 TITL {0:1} p.43 +1 CONT +1 FILE {1:1} p.47 +1 CONT +1 <> {0:M} p.33 +0 @N0013@ NOTE Media note test: Multimedia link to linked form v5.5.1 file +1 CONT n @XREF:OBJE@ OBJE {1:1} +1 CONT +1 FILE {1:M} p.54 +1 CONT +2 FORM {1:1} p.54 +1 CONT +3 TYPE {0:1} p.62 +1 CONT +2 TITL {0:1} p.48 +1 CONT +1 REFN {0:M} p.63, 64 >> note? +1 CONT +2 TYPE {0:1} p.64 +1 CONT +1 RIN {0:1} p.43 >> Attribute ID? +1 CONT +1 <> {0:M} p.37 +1 CONT +1 <> {0:M} p.39 +1 CONT +1 <> {0:1} p.31 +0 @N0014@ NOTE Media note test: Multimedia link embedded form v5.5.1 +1 CONT This note is not in the 5.5.1 spec, but is an obvious extrapolation from 5.5. +1 CONT n OBJE +1 CONT +1 FILE {1:M} p.54 +1 CONT +2 FORM {1:1} p.54 +1 CONT +3 MEDI {0:1} p.62 +1 CONT +1 TITL {0:1} p.48 +0 @N0015@ NOTE +1 CONC A note on the FTM media, to see how this integrates... The DATE line +1 CONC is bad; it doesnt follow Gedcom standard at all, and includes the time. +1 CONT The TEXT line comes from the FTM media description. This is the media Note. +0 @N0016@ NOTE Multimedia link to linked form FTM style +1 CONT n @XREF:OBJE@ OBJE {1:1} +1 CONT +1 FILE {1:M} p.54 +1 CONT +2 TITL {0:1} p.43 +1 CONT +2 DATE text string from media page, sometimes populated from exif "mm/dd/yyyy hh:mn:ss AM" +1 CONT +2 TEXT text string from FTM media description sometimes populated from exif comments +1 CONT +1 <> {0:M} p.33 +0 @N0017@ NOTE Multimedia link to linked form v5.5.1 with two files +0 @N0018@ NOTE Multimedia embedded 2nd copy v5.5 +0 TRLR diff --git a/data/tests/imp_MediaTest.gramps b/data/tests/imp_MediaTest.gramps new file mode 100644 index 000000000..efc15f8af --- /dev/null +++ b/data/tests/imp_MediaTest.gramps @@ -0,0 +1,279 @@ + + + +
+ + + Paul Culley + 11210 Olde Mint House Ln + Tomball + Tx + USA + 77375 + paulr2787@gmail.com + +
+ + + U + + The + Tester + + + + + + + + + + + + + + + 0 + + + + + + 77, 78 discussion of multimedia link with two files + 0 + + + + + + + A Great Photographer + + + The Testers personal files + The Tester + Name: Tester Publishing Operations, Inc.; Location: OSF world + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Media note test: Multimedia link embedded form v5.5 +n OBJE {1:1} p.55 ++1 FORM <MULTIMEDIA_FORMAT> {1:1} p.48 ++1 TITL <DESCRIPTIVE_TITLE> {0:1} p.43 ++1 FILE <MULTIMEDIA_FILE_REFERENCE> {1:1} p.47 ++1 <<NOTE_STRUCTURE>> {0:M} p.33 + + + Media note test: Multimedia link embedded form v5.5.1 +This note is not in the 5.5.1 spec, but is an obvious extrapolation from 5.5. +n OBJE ++1 FILE <MULTIMEDIA_FILE_REFN> {1:M} p.54 ++2 FORM <MULTIMEDIA_FORMAT> {1:1} p.54 ++3 MEDI <SOURCE_MEDIA_TYPE> {0:1} p.62 ++1 TITL <DESCRIPTIVE_TITLE> {0:1} p.48 + + + Multimedia embedded 2nd copy v5.5 + + + Records not imported into INDI (individual) Gramps ID I0001: + +Tag recognized but not supported Line 29: 4 MEDI photo + + + + SOMETEXT + + + Media note test: Multimedia link to linked form v5.5 blob +n @XREF:OBJE@ OBJE {1:1} ++1 FORM <MULTIMEDIA_FORMAT> {1:1} p.48 ++1 TITL <DESCRIPTIVE_TITLE> {0:1} p.43 ++1 <<NOTE_STRUCTURE>> {0:M} p.33 ++1 BLOB {1:1} ++2 CONT <ENCODED_MULTIMEDIA_LINE> {1:M} p.43 ++1 OBJE @<XREF:OBJE>@ /* chain to continued object */ {0:1} p.26 ++1 REFN <USER_REFERENCE_NUMBER> {0:M} p.55 ++2 TYPE <USER_REFERENCE_TYPE> {0:1} p.55 ++1 RIN <AUTOMATED_RECORD_ID> {0:1} p.38 ++1 <<CHANGE_DATE>> {0:1} p.29 + + + Records not imported into OBJE (multi-media object) Gramps ID M1: + +BLOB ignored Line 42: 1 BLOB + .HM.......k.1..F.jwA.Dzzzzw............A....1.........0U.66..E.8 + .......A..k.a6.A.......A..k.........../6....G.......0../..U..... + .w1/m........HC0..../...zzzzzzzz..5zzk..AnA..U..W6U....2rRrRrRrR + .Dw...............k.1.......1..A...5ykE/zzzx/.g//.Hxzk6/.Tzy/.k1 + /Dw/.Tvz.E5zzUE9/kHz.Tw2/DzzzEEA.kE2zk5yzk2/zzs21.U2/Dw/.Tw/.Tzy + /.fy/.HzzkHzzzo21Ds00.E2.UE2.U62/.k./Ds0.UE0/Do0..E8/UE2.U62.U9w + /.Tx/.20.jg2/jo2..9u/.0U.6A.zk +Line ignored as not understood Line 50: 1 OBJE @M2@ + + + + Records not imported into OBJE (multi-media object) Gramps ID M2: + +BLOB ignored Line 61: 1 BLOB + 67890gramps doesn't do this anyway, so don't bother doing it right. + + + + Media note test: Multimedia link to linked form Gramps style v5.5ish file +n @XREF:OBJE@ OBJE {1:1} ++1 FORM <MULTIMEDIA_FORMAT> {1:1} p.48 ++1 TITL <DESCRIPTIVE_TITLE> {0:1} p.43 ++1 FILE <MULTIMEDIA_FILE_REFERENCE> {1:1} p.47 ++1 <<NOTE_STRUCTURE>> {0:M} p.33 + + + Records not imported into OBJE (multi-media object) Gramps ID M3: + +Could not import test.jpg Line 66: 1 FILE test.jpg + + + + SOMETEXT + + + Media note test: Multimedia link to linked form v5.5.1 file +n @XREF:OBJE@ OBJE {1:1} ++1 FILE <MULTIMEDIA_FILE_REFN> {1:M} p.54 ++2 FORM <MULTIMEDIA_FORMAT> {1:1} p.54 ++3 TYPE <SOURCE_MEDIA_TYPE> {0:1} p.62 ++2 TITL <DESCRIPTIVE_TITLE> {0:1} p.48 ++1 REFN <USER_REFERENCE_NUMBER> {0:M} p.63, 64 >> note? ++2 TYPE <USER_REFERENCE_TYPE> {0:1} p.64 ++1 RIN <AUTOMATED_RECORD_ID> {0:1} p.43 >> Attribute ID? ++1 <<NOTE_STRUCTURE>> {0:M} p.37 ++1 <<SOURCE_CITATION>> {0:M} p.39 ++1 <<CHANGE_DATE>> {0:1} p.31 + + + who shall remain un-named + + + Records not imported into OBJE (multi-media object) Gramps ID M4: + +Could not import test.jpg Line 72: 1 FILE test.jpg +Skipped subordinate line Line 74: 3 TYPE photo +Skipped subordinate line Line 75: 2 TITL Multimedia link to linked form v5.5.1 file + + + + A fine gentelman was he, upstanding in his community and a great believer in the testing of open source software. + + + A note on the FTM media, to see how this integrates... The DATE line is bad; it doesnt follow Gedcom standard at all, and includes the time. +The TEXT line comes from the FTM media description. This is the media Note. + + + Multimedia link to linked form FTM style +n @XREF:OBJE@ OBJE {1:1} ++1 FILE <MULTIMEDIA_FILE_REFN> {1:M} p.54 ++2 TITL <DESCRIPTIVE_TITLE> {0:1} p.43 ++2 DATE text string from media page, sometimes populated from exif "mm/dd/yyyy hh:mn:ss AM" ++2 TEXT text string from FTM media description sometimes populated from exif comments ++1 <<NOTE_STRUCTURE>> {0:M} p.33 + + + Records not imported into OBJE (multi-media object) Gramps ID M5: + +Could not import test.jpg Line 87: 1 FILE test.jpg + + + + SOMETEXT + + + Multimedia link to linked form v5.5.1 with two files + + + A source who shall remain un-named + + + Records not imported into OBJE (multi-media object) Gramps ID M6: + +Could not import test.jpg Line 95: 1 FILE test.jpg +Skipped subordinate line Line 97: 3 TYPE photo +Skipped subordinate line Line 98: 2 TITL Multimedia link to linked form v5.5.1 with two files(1) +Multiple FILE in a single OBJE ignored Line 99: 1 FILE test1.jpg +Skipped subordinate line Line 100: 2 FORM jpeg +Skipped subordinate line Line 101: 3 TYPE photo +Skipped subordinate line Line 102: 2 TITL Multimedia link to linked form v5.5.1 with two files(2) + + + +
diff --git a/gramps/plugins/lib/libgedcom.py b/gramps/plugins/lib/libgedcom.py index e4f436c2e..fec2d9d0d 100755 --- a/gramps/plugins/lib/libgedcom.py +++ b/gramps/plugins/lib/libgedcom.py @@ -2458,27 +2458,45 @@ class GedcomParser(UpdateCallback): # # Parse table for <> below the level 0 OBJE tag # - # n @@ OBJE {1:1} - # +1 FORM {1:1} - # +1 TITL {0:1} - # +1 <> {0:M} - # +1 <> {0:M} - # +1 BLOB {1:1} - # +2 CONT {1:M} - # +1 OBJE @@ /* chain to continued object */ {0:1} - # +1 REFN {0:M} - # +2 TYPE {0:1} - # +1 RIN {0:1} + # n @XREF:OBJE@ OBJE {1:1} # v5.5 layout + # +1 FILE {1:1} # de-facto extension + # +1 FORM {1:1} + # +1 TITL {0:1} + # +1 <> {0:M} + # +1 BLOB {1:1} # Deprecated, no support + # +2 CONT {1:M} + # +1 OBJE @@ /* chain */ {0:1} # Deprecated, no support + # +1 REFN {0:M} + # +2 TYPE {0:1} + # +1 RIN {0:1} + # +1 <> {0:1} + # + # n @XREF:OBJE@ OBJE {1:1} # v5.5.1 layout + # +1 FILE {1:M} # multi files, no support + # +2 FORM {1:1} + # +3 TYPE {0:1} + # +2 TITL {0:1} + # +2 DATE {0:1} # FTM extension + # +2 TEXT {0:1} # FTM extension + # +1 REFN {0:M} + # +2 TYPE {0:1} + # +1 RIN {0:1} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:1} self.obje_func = { TOKEN_FORM : self.__obje_form, + TOKEN_TYPE : self.__obje_type, # v5.5.1 TOKEN_TITL : self.__obje_title, - TOKEN_FILE : self.__obje_file, + TOKEN_FILE : self.__obje_file, # de-facto extension + TOKEN_TEXT : self.__obje_text, # FTM extension + TOKEN_DATE : self.__obje_date, # FTM extension TOKEN_NOTE : self.__obje_note, TOKEN_RNOTE : self.__obje_note, + TOKEN_SOUR : self.__obje_sour, TOKEN_BLOB : self.__obje_blob, TOKEN_REFN : self.__obje_refn, - TOKEN_TYPE : self.__obje_type, TOKEN_RIN : self.__obje_rin, TOKEN_CHAN : self.__obje_chan, } @@ -6504,17 +6522,32 @@ class GedcomParser(UpdateCallback): def __parse_obje(self, line): """ - n @XREF:OBJE@ OBJE {1:1} - +1 FORM {1:1} p.* - +1 TITL {0:1} p.* - +1 <> {0:M} p.* - +1 BLOB {1:1} - +2 CONT {1:M} p.* - +1 OBJE @@ /* chain to continued object */ {0:1} p.* - +1 REFN {0:M} p.* - +2 TYPE {0:1} p.* - +1 RIN {0:1} p.* - +1 <> {0:1} p.* + n @XREF:OBJE@ OBJE {1:1} # v5.5 layout + +1 FILE {1:1} # de-facto extension + +1 FORM {1:1} + +1 TITL {0:1} + +1 <> {0:M} p.* + +1 BLOB {1:1} # Deprecated, no support + +2 CONT {1:M} + +1 OBJE @@ /* chain */ {0:1} # Deprecated, no support + +1 REFN {0:M} + +2 TYPE {0:1} + +1 RIN {0:1} + +1 <> {0:1} + + n @XREF:OBJE@ OBJE {1:1} # v5.5.1 layout + +1 FILE {1:M} # multi files, no support + +2 FORM {1:1} + +3 TYPE {0:1} + +2 TITL {0:1} + +2 DATE {0:1} # FTM extension + +2 TEXT # FTM extension + +1 REFN {0:M} + +2 TYPE {0:1} + +1 RIN {0:1} + +1 <> {0:M} + +1 <> {0:M} + +1 <> {0:1} """ gid = line.token_text.strip() media = self.__find_or_create_media(self.oid_map[gid]) @@ -6554,6 +6587,13 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ + # The following checks for the odd "feature" of GEDCOM 5.5.1 that + # allows multiple files to be attached to a single OBJE; not supported + if state.media.get_path() != "": + self.__add_msg(_("Multiple FILE in a single OBJE ignored"), + line, state) + self.__skip_subordinate_levels(state.level+1, state) + return res = urlparse(line.data) if line.data != '' and (res.scheme == '' or res.scheme == 'file'): (file_ok, filename) = self.__find_file(line.data, self.dir_path) @@ -6580,6 +6620,31 @@ class GedcomParser(UpdateCallback): """ state.media.set_description(line.data) +# FTM non-standard TEXT in OBJE, treat as note. + def __obje_text(self, line, state): + """ + @param line: The current line in GedLine format + @type line: GedLine + @param state: The current state + @type state: CurrentState + """ + new_note = Note(line.data) + new_note.set_gramps_id(self.nid_map[""]) + new_note.set_handle(create_id()) + new_note.set_type(NoteType.MEDIA) + self.dbase.commit_note(new_note, self.trans, new_note.change) + state.media.add_note(new_note.get_handle()) + +# FTM non-standard DATE in OBJE, treat as Media Date. + def __obje_date(self, line, state): + """ + @param line: The current line in GedLine format + @type line: GedLine + @param state: The current state + @type state: CurrentState + """ + state.media.set_date_object(line.data) + def __obje_note(self, line, state): """ @param line: The current line in GedLine format @@ -6589,6 +6654,15 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.media, state.level+1, state) + def __obje_sour(self, line, state): + """ + @param line: The current line in GedLine format + @type line: GedLine + @param state: The current state + @type state: CurrentState + """ + state.media.add_citation(self.handle_source(line, state.level, state)) + def __obje_blob(self, line, state): """ @param line: The current line in GedLine format @@ -6606,8 +6680,22 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - self.__add_msg(_("REFN ignored"), line, state) - self.__skip_subordinate_levels(state.level+1, state) + attr = Attribute() + attr.set_type(line.token_text) # Atrribute : REFN + attr.set_value(line.data) + # if there is a subsequent TYPE, we add it as a note to the attribute + while True: + line = self.__get_next_line() + if self.__level_is_finished(line, state.level+1): + break + elif line.token == TOKEN_TYPE: + new_note = Note(line.data) + new_note.set_gramps_id(self.nid_map[""]) + new_note.set_handle(create_id()) + new_note.set_type('REFN-TYPE') + self.dbase.commit_note(new_note, self.trans, new_note.change) + attr.add_note(new_note.get_handle()) + state.media.attribute_list.append(attr) def __obje_type(self, line, state): """ @@ -6616,8 +6704,10 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - self.__add_msg(_("Multimedia REFN:TYPE ignored"), line, state) - self.__skip_subordinate_levels(state.level+1, state) + attr = Attribute() + attr.set_type(_('Media-Type')) + attr.set_value(line.data) # (Photo, Audio, Book, etc.) + state.media.attribute_list.append(attr) def __obje_rin(self, line, state): """ @@ -6626,8 +6716,10 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - self.__add_msg(_("Mutimedia RIN ignored"), line, state) - self.__skip_subordinate_levels(state.level+1, state) + attr = Attribute() + attr.set_type(line.token_text) # Attribute: RIN + attr.set_value(line.data) + state.media.attribute_list.append(attr) def __obje_chan(self, line, state): """ @@ -7564,6 +7656,8 @@ class GedcomParser(UpdateCallback): self.__add_msg(_("Could not import %s") % filename) else: path = filename + # Multiple references to the same media silently drops the later + # ones, even if title, notes etc. are different photo_handle = self.media_map.get(path) if photo_handle is None: photo = Media() @@ -7574,14 +7668,14 @@ class GedcomParser(UpdateCallback): photo.set_mime_type(get_type(full_path)) else: photo.set_mime_type(MIME_MAP.get(form.lower(), 'unknown')) + if note: + photo.add_note(note) self.dbase.add_media(photo, self.trans) self.media_map[path] = photo.handle else: photo = self.dbase.get_media_from_handle(photo_handle) oref = MediaRef() oref.set_reference_handle(photo.handle) - if note: - oref.add_note(note) obj.add_media_reference(oref) def __build_event_pair(self, state, event_type, event_map, description):