def __select_file(self, obj): """ Call back function to handle the open button press """ if self.dir: my_action = Gtk.FileChooserAction.SELECT_FOLDER else: my_action = Gtk.FileChooserAction.SAVE dialog = Gtk.FileChooserDialog(self.title, action=my_action, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) name = os.path.basename(conv_to_unicode(self.entry.get_text())) if self.dir: if os.path.isdir(name): dialog.set_current_name(name) elif os.path.isdir(os.path.basename(name)): dialog.set_current_name(os.path.basename(name)) else: dialog.set_current_name(name) dialog.set_current_folder(self.__base_path) dialog.present() status = dialog.run() if status == Gtk.ResponseType.OK: self.set_filename(conv_to_unicode(dialog.get_filename())) dialog.destroy()
def __really_delete_db(self): """ Delete the selected database. If the database is open, close it first. Then scan the database directory, deleting the files, and finally removing the directory. """ # close the database if the user has requested to delete the # active database if self.data_to_delete[PATH_COL] == self.active: self.dbstate.no_database() store, node = self.selection.get_selected() path = store.get_path(node) node = self.model.get_iter(path) filename = conv_to_unicode(self.model.get_value(node, FILE_COL), 'utf8') try: name_file = open(filename, "r") file_name_to_delete = name_file.read() name_file.close() remove_filename(file_name_to_delete) directory = conv_to_unicode(self.data_to_delete[1], 'utf8') for (top, dirs, files) in os.walk(directory): for filename in files: os.unlink(os.path.join(top, filename)) os.rmdir(directory) except (IOError, OSError) as msg: DbManager.ERROR(_("Could not delete Family Tree"), str(msg)) # rebuild the display self.__populate()
def add_child_links_to_families(self): """ returns string of Graphviz edges linking parents to families or children """ # Hash people in a dictionary for faster inclusion checking person_dict = dict([conv_to_unicode(handle, 'utf-8'), 1] for handle in self.person_handles) for person_handle in self.person_handles: person = self.database.get_person_from_handle(person_handle) p_id = person.get_gramps_id() for fam_handle in person.get_parent_family_handle_list(): family = self.database.get_family_from_handle(fam_handle) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() for child_ref in family.get_child_ref_list(): if child_ref.ref == conv_to_unicode(person_handle, 'utf-8'): frel = child_ref.frel mrel = child_ref.mrel break if (self.show_families and ((father_handle and father_handle in person_dict) or (mother_handle and mother_handle in person_dict))): # Link to the family node if either parent is in graph self.add_family_link(p_id, family, frel, mrel) else: # Link to the parents' nodes directly, if they are in graph if father_handle and father_handle in person_dict: self.add_parent_link(p_id, father_handle, frel) if mother_handle and mother_handle in person_dict: self.add_parent_link(p_id, mother_handle, mrel)
def __really_delete_db(self): """ Delete the selected database. If the database is open, close it first. Then scan the database directory, deleting the files, and finally removing the directory. """ # close the database if the user has requested to delete the # active database if self.data_to_delete[PATH_COL] == self.active: self.dbstate.no_database() store, node = self.selection.get_selected() path = store.get_path(node) node = self.model.get_iter(path) filename = conv_to_unicode(self.model.get_value(node, FILE_COL), 'utf8') try: name_file = open(filename, "r") file_name_to_delete=name_file.read() name_file.close() remove_filename(file_name_to_delete) directory = conv_to_unicode(self.data_to_delete[1], 'utf8') for (top, dirs, files) in os.walk(directory): for filename in files: os.unlink(os.path.join(top, filename)) os.rmdir(directory) except (IOError, OSError) as msg: DbManager.ERROR(_("Could not delete Family Tree"), str(msg)) # rebuild the display self.__populate()
def add_child_links_to_families(self): """ returns string of GraphViz edges linking parents to families or children """ # Hash people in a dictionary for faster inclusion checking person_dict = dict([conv_to_unicode(handle, 'utf-8'), 1] for handle in self.person_handles) for person_handle in self.person_handles: person = self.database.get_person_from_handle(person_handle) p_id = person.get_gramps_id() for fam_handle in person.get_parent_family_handle_list(): family = self.database.get_family_from_handle(fam_handle) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() for child_ref in family.get_child_ref_list(): if child_ref.ref == conv_to_unicode( person_handle, 'utf-8'): frel = child_ref.frel mrel = child_ref.mrel break if (self.show_families and ((father_handle and father_handle in person_dict) or (mother_handle and mother_handle in person_dict))): # Link to the family node if either parent is in graph self.add_family_link(p_id, family, frel, mrel) else: # Link to the parents' nodes directly, if they are in graph if father_handle and father_handle in person_dict: self.add_parent_link(p_id, father_handle, frel) if mother_handle and mother_handle in person_dict: self.add_parent_link(p_id, mother_handle, mrel)
def __select_file(self, obj): """ Call back function to handle the open button press """ if self.dir: my_action = Gtk.FileChooserAction.SELECT_FOLDER else: my_action = Gtk.FileChooserAction.SAVE dialog = Gtk.FileChooserDialog(self.title, self.parent, action=my_action, buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Open'), Gtk.ResponseType.OK)) name = os.path.basename(conv_to_unicode(self.entry.get_text())) if self.dir: if os.path.isdir(name): dialog.set_current_name(name) elif os.path.isdir(os.path.basename(name)): dialog.set_current_name(os.path.basename(name)) else: dialog.set_current_name(name) dialog.set_current_folder(self.__base_path) dialog.present() status = dialog.run() if status == Gtk.ResponseType.OK: self.set_filename(conv_to_unicode(dialog.get_filename())) dialog.destroy()
def __handle_import_option(self, value, family_tree_format): """ Handle the "-i" or "--import" option. Only Files supported by a plugin can be imported, so not Family Trees. """ # Need to convert path/filename to unicode before opening # For non latin characters in Windows path/file/user names fname = conv_to_unicode(value, sys.stdin.encoding) fullpath = os.path.abspath(os.path.expanduser(fname)) if fname != '-' and not os.path.exists(fullpath): self.__error(_('Error: Import file %s not found.') % fname) sys.exit(0) if family_tree_format is None: # Guess the file format based on the file extension. # This will get the lower case extension without a period, # or an empty string. family_tree_format = os.path.splitext(fname)[-1][1:].lower() pmgr = BasePluginManager.get_instance() plugin_found = False for plugin in pmgr.get_import_plugins(): if family_tree_format == plugin.get_extension(): plugin_found = True if plugin_found: self.imports.append((fname, family_tree_format)) else: self.__error(_('Error: Unrecognized type: "%(format)s" for ' 'import file: %(filename)s') % {'format' : family_tree_format, 'filename' : fname}) sys.exit(0)
def __handle_open_option(self, value, create): """ Handle the "-O" or "--open" and "-C" or "--create" options. Only Family trees or a dir with a family tree can be opened. If create is True, then create the tree if it doesn't exist. """ if value is None: return None value = conv_to_unicode(value, sys.stdin.encoding) db_path = self.__deduce_db_path(value) if db_path: # We have a potential database path. # Check if it is good. if not self.check_db(db_path, self.force_unlock): sys.exit(0) if create: self.__error( _("Error: Family Tree '%s' already exists.\n" "The '-C' option cannot be used.") % value) sys.exit(0) return db_path elif create: # create the tree here, and continue dbid = config.get('behavior.database-backend') db_path, title = self.dbman.create_new_db_cli(title=value, dbid=dbid) return db_path else: self.__error( _('Error: Input Family Tree "%s" does not exist.\n' "If GEDCOM, Gramps-xml or grdb, use the -i option " "to import into a Family Tree instead.") % value) sys.exit(0)
def save(self): """ Perform the actual Save As/Export operation. Depending on the success status, set the text for the final page. """ success = False try: if (self.option_box_instance and hasattr(self.option_box_instance, "no_fileselect")): filename = "" else: filename = conv_to_unicode(self.chooser.get_filename()) config.set('paths.recent-export-dir', os.path.split(filename)[0]) ix = self.get_selected_format_index() config.set('behavior.recent-export-type', ix) export_function = self.map_exporters[ix].get_export_function() success = export_function(self.dbstate.db, filename, User(error=ErrorDialog, callback=self.callback), self.option_box_instance) except: #an error not catched in the export_function itself success = False log.error(_("Error exporting your Family Tree"), exc_info=True) return success
def export_results(self, button): """ Export the results to a text file. """ chooser = Gtk.FileChooserDialog( _("Export results to a text file"), self.uistate.window, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) chooser.set_do_overwrite_confirmation(True) while True: value = chooser.run() filename = chooser.get_filename() filename = conv_to_unicode(filename) if value == Gtk.ResponseType.OK: if filename: chooser.destroy() break else: chooser.destroy() return try: with io.open(filename, 'w') as report_file: for title, model in zip(self.titles, self.models): self.export_page(report_file, title, model) except IOError as err: WarningDialog( self.window_name, _('Error when writing the report: %s') % err.strerror, self.window)
def export(self, obj): chooser = Gtk.FileChooserDialog( _("Export View as Spreadsheet"), self.uistate.window, Gtk.FileChooserAction.SAVE, (_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Save'), Gtk.ResponseType.OK)) chooser.set_do_overwrite_confirmation(True) combobox = Gtk.ComboBoxText() label = Gtk.Label(label=_("Format:")) label.set_halign(Gtk.Align.END) box = Gtk.Box() box.pack_start(label, True, True, padding=12) box.pack_start(combobox, False, False, 0) combobox.append_text(_('CSV')) combobox.append_text(_('OpenDocument Spreadsheet')) combobox.set_active(0) box.show_all() chooser.set_extra_widget(box) while True: value = chooser.run() fn = chooser.get_filename() fn = conv_to_unicode(fn) fl = combobox.get_active() if value == Gtk.ResponseType.OK: if fn: chooser.destroy() break else: chooser.destroy() return self.write_tabbed_file(fn, fl)
def __select_file(self, obj): """ Select a file from the file system. """ fcd = Gtk.FileChooserDialog( _("Load Addon"), buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) name = self.install_addon_path.get_text() dir = os.path.dirname(name) if not os.path.isdir(dir): dir = USER_HOME name = '' elif not os.path.isfile(name): name = '' fcd.set_current_folder(dir) if name: fcd.set_filename(name) status = fcd.run() if status == Gtk.ResponseType.OK: path = conv_to_unicode(fcd.get_filename()) if path: self.install_addon_path.set_text(path) fcd.destroy()
def __handle_import_option(self, value, family_tree_format): """ Handle the "-i" or "--import" option. Only Files supported by a plugin can be imported, so not Family Trees. """ # Need to convert path/filename to unicode before opening # For non latin characters in Windows path/file/user names fname = conv_to_unicode(value, sys.stdin.encoding) fullpath = os.path.abspath(os.path.expanduser(fname)) if fname != '-' and not os.path.exists(fullpath): self.__error(_('Error: Import file %s not found.') % fname) sys.exit(0) if family_tree_format is None: # Guess the file format based on the file extension. # This will get the lower case extension without a period, # or an empty string. family_tree_format = os.path.splitext(fname)[-1][1:].lower() pmgr = BasePluginManager.get_instance() plugin_found = False for plugin in pmgr.get_import_plugins(): if family_tree_format == plugin.get_extension(): plugin_found = True if plugin_found: self.imports.append((fname, family_tree_format)) else: self.__error( _('Error: Unrecognized type: "%(format)s" for ' 'import file: %(filename)s') % { 'format': family_tree_format, 'filename': fname }) sys.exit(0)
def __handle_open_option(self, value, create): """ Handle the "-O" or "--open" and "-C" or "--create" options. Only Family trees or a dir with a family tree can be opened. If create is True, then create the tree if it doesn't exist. """ if value is None: return None value = conv_to_unicode(value, sys.stdin.encoding) db_path = self.__deduce_db_path(value) if db_path: # We have a potential database path. # Check if it is good. if not self.check_db(db_path, self.force_unlock): sys.exit(0) if create: self.__error( _("Error: Family Tree '%s' already exists.\n" "The '-C' option cannot be used.") % value) sys.exit(0) return db_path elif create: # create the tree here, and continue db_path, title = self.dbman.create_new_db_cli(title=value) return db_path else: self.__error( _('Error: Input Family Tree "%s" does not exist.\n' "If GEDCOM, Gramps-xml or grdb, use the -i option " "to import into a Family Tree instead.") % value) sys.exit(0)
def on_name_changed(self, *obj): """ Called anytime the filename text window changes. Checks to see if the file exists. If it does, the image is loaded into the preview window. """ fname = self.file_text.get_filename() if not fname: return filename = conv_to_unicode(fname) basename = os.path.basename(filename) (root, ext) = os.path.splitext(basename) old_title = str(self.description.get_text()) if old_title == '' or old_title == self.temp_name: self.description.set_text(root) self.temp_name = root filename = find_file( filename) if filename: mtype = get_type(filename) if mtype and mtype.startswith("image"): image = scale_image(filename, THUMBSCALE) else: image = find_mime_type_pixbuf(mtype) self.image.set_from_pixbuf(image)
def save(self): """ Perform the actual Save As/Export operation. Depending on the success status, set the text for the final page. """ success = False try: if (self.option_box_instance and hasattr(self.option_box_instance, "no_fileselect")): filename = "" else: filename = conv_to_unicode(self.chooser.get_filename()) config.set('paths.recent-export-dir', os.path.split(filename)[0]) ix = self.get_selected_format_index() config.set('behavior.recent-export-type', ix) export_function = self.map_exporters[ix].get_export_function() success = export_function( self.dbstate.db, filename, User(error=ErrorDialog, callback=self.callback), self.option_box_instance) except: #an error not catched in the export_function itself success = False log.error(_("Error exporting your Family Tree"), exc_info=True) return success
def on_name_changed(self, *obj): """ Called anytime the filename text window changes. Checks to see if the file exists. If it does, the image is loaded into the preview window. """ fname = self.file_text.get_filename() if not fname: return filename = conv_to_unicode(fname) basename = os.path.basename(filename) (root, ext) = os.path.splitext(basename) old_title = str(self.description.get_text()) if old_title == '' or old_title == self.temp_name: self.description.set_text(root) self.temp_name = root filename = find_file(filename) if filename: mtype = get_type(filename) if mtype and mtype.startswith("image"): image = scale_image(filename, THUMBSCALE) else: image = find_mime_type_pixbuf(mtype) self.image.set_from_pixbuf(image)
def __select_file(self, obj): """ Select a file from the file system. """ fcd = Gtk.FileChooserDialog(_("Load Addon"), buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Open'), Gtk.ResponseType.OK)) name = self.install_addon_path.get_text() dir = os.path.dirname(name) if not os.path.isdir(dir): dir = USER_HOME name = '' elif not os.path.isfile(name): name = '' fcd.set_current_folder(dir) if name: fcd.set_filename(name) status = fcd.run() if status == Gtk.ResponseType.OK: path = conv_to_unicode(fcd.get_filename()) if path: self.install_addon_path.set_text(path) fcd.destroy()
def export_results(self, button): """ Export the results to a text file. """ chooser = Gtk.FileChooserDialog( _("Export results to a text file"), self.uistate.window, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) chooser.set_do_overwrite_confirmation(True) while True: value = chooser.run() filename = chooser.get_filename() filename = conv_to_unicode(filename) if value == Gtk.ResponseType.OK: if filename: chooser.destroy() break else: chooser.destroy() return try: with io.open(filename, 'w') as report_file: for title, model in zip(self.titles, self.models): self.export_page(report_file, title, model) except IOError as err: WarningDialog(self.window_name, _('Error when writing the report: %s') % err.strerror, self.window)
def _get_surn_from_model(self): """ Return new surname_list for storing in the name based on content of the model """ new_list = [] for idx in range(len(self.model)): node = self.model.get_iter(idx) surn = self.model.get_value(node, 5) surn.set_prefix(conv_to_unicode(self.model.get_value(node, 0), 'UTF-8')) surn.set_surname(conv_to_unicode(self.model.get_value(node, 1), 'UTF-8')) surn.set_connector(conv_to_unicode(self.model.get_value(node, 2), 'UTF-8')) surn.get_origintype().set(conv_to_unicode(self.model.get_value(node, 3), 'UTF-8')) surn.set_primary(self.model.get_value(node, 4)) new_list += [surn] return new_list
def run(self): """ Runs the dialog, returning None if nothing has been chosen, or the path and name if something has been selected """ while True: value = self.top.run() if value == Gtk.ResponseType.OK: store, node = self.selection.get_selected() # don't open a locked file if store.get_value(node, ICON_COL) == 'gramps-lock': self.__ask_to_break_lock(store, node) continue # don't open a version if len(store.get_path(node).get_indices()) > 1: continue if node: self.top.destroy() del self.selection del self.name_renderer path = conv_to_unicode(store.get_value(node, PATH_COL), 'utf8') return (path, store.get_value(node, NAME_COL)) else: self.top.destroy() del self.selection del self.name_renderer return None
def export(self, obj): chooser = Gtk.FileChooserDialog( _("Export View as Spreadsheet"), self.uistate.window, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) chooser.set_do_overwrite_confirmation(True) combobox = Gtk.ComboBoxText() label = Gtk.Label(label=_("Format:")) label.set_alignment(1.0, 0.5) box = Gtk.HBox() box.pack_start(label, True, True, padding=12) box.pack_start(combobox, False, False, 0) combobox.append_text(_('CSV')) combobox.append_text(_('OpenDocument Spreadsheet')) combobox.set_active(0) box.show_all() chooser.set_extra_widget(box) while True: value = chooser.run() fn = chooser.get_filename() fn = conv_to_unicode(fn) fl = combobox.get_active() if value == Gtk.ResponseType.OK: if fn: chooser.destroy() break else: chooser.destroy() return self.write_tabbed_file(fn, fl)
def save(self, *obj): self.ok_button.set_sensitive(False) if self.object_is_empty(): ErrorDialog( _("Cannot save media object"), _("No data exists for this media object. Please " "enter data or cancel the edit.")) self.ok_button.set_sensitive(True) return (uses_dupe_id, id) = self._uses_duplicate_id() if uses_dupe_id: prim_object = self.get_from_gramps_id(id) name = prim_object.get_description() msg1 = _("Cannot save media object. ID already exists.") msg2 = _("You have attempted to use the existing Gramps ID with " "value %(id)s. This value is already used by '" "%(prim_object)s'. Please enter a different ID or leave " "blank to get the next available ID value.") % { 'id': id, 'prim_object': name } ErrorDialog(msg1, msg2) self.ok_button.set_sensitive(True) return path = conv_to_unicode(self.file_path.get_text()) full_path = media_path_full(self.db, path) if os.path.isfile(full_path): self.determine_mime() else: msg1 = _("There is no media matching the current path value!") msg2 = _("You have attempted to use the path with " "value '%(path)s'. This path does not exist!" " Please enter a different path") % { 'path': path } ErrorDialog(msg1, msg2) self.ok_button.set_sensitive(True) return self.obj.set_path(path) with DbTxn('', self.db) as trans: if not self.obj.get_handle(): self.db.add_object(self.obj, trans) msg = _("Add Media Object (%s)") % self.obj.get_description() else: if not self.obj.get_gramps_id(): self.obj.set_gramps_id( self.db.find_next_object_gramps_id()) self.db.commit_media_object(self.obj, trans) msg = _("Edit Media Object (%s)") % self.obj.get_description() trans.set_description(msg) if self.callback: self.callback(self.obj) self.close()
def get_next_line(self): self.lineno += 1 line = self.f.readline() try: line = conv_to_unicode(line) except GrampsImportError as err: self.errmsg(str(err)) if line: try: line = str(line.strip()) except UnicodeDecodeError: line = conv_to_unicode(line.strip(), self.encoding) else: line = None return line
def column_description(self, data): descr = data[4] if isinstance(descr, str): return descr try: return str(descr) except: return conv_to_unicode(descr, 'latin1')
def column_description(self, data): descr = data[4] if isinstance(descr, UNITYPE): return descr try: return cuni(descr) except: return conv_to_unicode(descr, 'latin1')
def rename_database(self, filepath, new_text): """ Renames the database by writing the new value to the name.txt file Returns old_name, new_name if success, None, None if no success """ try: filepath = conv_to_unicode(filepath, 'utf8') new_text = conv_to_unicode(new_text, 'utf8') name_file = io.open(filepath, "r", encoding='utf8') old_text = name_file.read() name_file.close() name_file = io.open(filepath, "w", encoding='utf8') name_file.write(new_text) name_file.close() except (OSError, IOError) as msg: CLIDbManager.ERROR(_("Could not rename Family Tree"), str(msg)) return None, None return old_text, new_text
def parse_target_frame(self): """Parse the target frame of the dialog. If the target filename is empty this routine returns a special value of None to tell the calling routine to give up. This function also saves the current directory so that any future reports will default to the most recently used directory.""" self.target_path = conv_to_unicode( self.target_fileentry.get_full_path(0)) if not self.target_path: return None # First we check whether the selected path exists if os.path.exists(self.target_path): # selected path is an existing dir and we need a dir if os.path.isdir(self.target_path): # check whether the dir has rwx permissions if not os.access(self.target_path, os.R_OK | os.W_OK | os.X_OK): ErrorDialog( _('Permission problem'), _("You do not have permission to write " "under the directory %s\n\n" "Please select another directory or correct " "the permissions.") % self.target_path) return None # selected path is an existing file and we need a file if os.path.isfile(self.target_path): a = OptionDialog( _('File already exists'), _('You can choose to either overwrite the ' 'file, or change the selected filename.'), _('_Overwrite'), None, _('_Change filename'), None) if a.get_response() == Gtk.ResponseType.YES: return None # selected path does not exist yet else: # we will need to create the file/dir # need to make sure we can create in the parent dir parent_dir = os.path.dirname(os.path.normpath(self.target_path)) if not os.access(parent_dir, os.W_OK): ErrorDialog( _('Permission problem'), _("You do not have permission to create " "%s\n\n" "Please select another path or correct " "the permissions.") % self.target_path) return None self.set_default_directory(os.path.dirname(self.target_path) + os.sep) self.options.handler.output = self.target_path return 1
def _undo_delete(self, undo_action): if not isinstance(undo_action.text, str): undo_action.text = conv_to_unicode(undo_action.text, 'utf-8') with warnings.catch_warnings(): warnings.simplefilter('ignore') self.insert_text(undo_action.text, undo_action.start) if undo_action.delete_key_used: self.set_position(undo_action.start) else: self.set_position(undo_action.end)
def rename_database(self, filepath, new_text): """ Renames the database by writing the new value to the name.txt file Returns old_name, new_name if success, None, None if no success """ try: filepath = conv_to_unicode(filepath, 'utf8') new_text = conv_to_unicode(new_text, 'utf8') name_file = io.open(filepath, "r", encoding='utf8') old_text=name_file.read() name_file.close() name_file = io.open(filepath, "w", encoding='utf8') name_file.write(new_text) name_file.close() except (OSError, IOError) as msg: CLIDbManager.ERROR(_("Could not rename Family Tree"), str(msg)) return None, None return old_text, new_text
def __next__(self): "Read the next line of the file." row = next(self.reader) rowlist = [conv_to_unicode(s, "utf-8") for s in row] # Add check for Byte Order Mark (Windows, Notepad probably): if self.first_row: if len(rowlist) > 0 and rowlist[0].startswith("\ufeff"): rowlist[0] = rowlist[0][1:] self.first_row = False return rowlist
def _get_surn_from_model(self): """ Return new surname_list for storing in the name based on content of the model """ new_list = [] for idx in range(len(self.model)): node = self.model.get_iter(idx) surn = self.model.get_value(node, 5) surn.set_prefix( conv_to_unicode(self.model.get_value(node, 0), 'UTF-8')) surn.set_surname( conv_to_unicode(self.model.get_value(node, 1), 'UTF-8')) surn.set_connector( conv_to_unicode(self.model.get_value(node, 2), 'UTF-8')) surn.get_origintype().set( conv_to_unicode(self.model.get_value(node, 3), 'UTF-8')) surn.set_primary(self.model.get_value(node, 4)) new_list += [surn] return new_list
def find_next_db_name(name_list): """ Scan the name list, looking for names that do not yet exist. Use the DEFAULT_TITLE as the basis for the database name. """ i = 1 while True: title = "%s %d" % (DEFAULT_TITLE, i) if title not in name_list: return conv_to_unicode(title) i += 1
def save(self, *obj): self.ok_button.set_sensitive(False) if self.object_is_empty(): ErrorDialog(_("Cannot save media object"), _("No data exists for this media object. Please " "enter data or cancel the edit.")) self.ok_button.set_sensitive(True) return (uses_dupe_id, id) = self._uses_duplicate_id() if uses_dupe_id: prim_object = self.get_from_gramps_id(id) name = prim_object.get_description() msg1 = _("Cannot save media object. ID already exists.") msg2 = _("You have attempted to use the existing Gramps ID with " "value %(id)s. This value is already used by '" "%(prim_object)s'. Please enter a different ID or leave " "blank to get the next available ID value.") % { 'id' : id, 'prim_object' : name } ErrorDialog(msg1, msg2) self.ok_button.set_sensitive(True) return path = conv_to_unicode(self.file_path.get_text()) full_path = media_path_full(self.db, path) if os.path.isfile(full_path): self.determine_mime() else: msg1 = _("There is no media matching the current path value!") msg2 = _("You have attempted to use the path with " "value '%(path)s'. This path does not exist!" " Please enter a different path") % { 'path' : path } ErrorDialog(msg1, msg2) self.ok_button.set_sensitive(True) return self.obj.set_path(path) with DbTxn('', self.db) as trans: if not self.obj.get_handle(): self.db.add_object(self.obj, trans) msg = _("Add Media Object (%s)") % self.obj.get_description() else: if not self.obj.get_gramps_id(): self.obj.set_gramps_id(self.db.find_next_object_gramps_id()) self.db.commit_media_object(self.obj, trans) msg = _("Edit Media Object (%s)") % self.obj.get_description() trans.set_description(msg) if self.callback: self.callback(self.obj) self.close()
def get_next_line(self): self.lineno += 1 line = self.f.readline() if line: try: line = cuni(line.strip()) except UnicodeDecodeError: line = conv_to_unicode(line.strip(), self.encoding) else: line = None return line
def __init__(self, text, length, position, editable): self.offset = position self.text = str(text) #unicode char can have length > 1 as it points in the buffer if not isinstance(text, str): text = conv_to_unicode(text, 'utf-8') charlength = len(text) self.length = charlength if charlength > 1 or self.text in ("\r", "\n", " "): self.mergeable = False else: self.mergeable = True
def check_fileselect(self, filechooser, event=None, show=True): """Given a filechooser, determine if it can be marked complete in the Assistant. Used as normal callback and event callback. For callback, we will have show=True """ filename = conv_to_unicode(filechooser.get_filename()) if not filename: self.set_page_complete(filechooser, False) else: folder = conv_to_unicode(filechooser.get_current_folder()) if not folder: folder = find_folder(filename) else: folder = find_folder(folder) #the file must be valid, not a folder, and folder must be valid if (filename and os.path.basename(filename.strip()) and folder): #this page of the assistant is complete self.set_page_complete(filechooser, True) else : self.set_page_complete(filechooser, False)
def check_fileselect(self, filechooser, event=None, show=True): """Given a filechooser, determine if it can be marked complete in the Assistant. Used as normal callback and event callback. For callback, we will have show=True """ filename = conv_to_unicode(filechooser.get_filename()) if not filename: self.set_page_complete(filechooser, False) else: folder = conv_to_unicode(filechooser.get_current_folder()) if not folder: folder = find_folder(filename) else: folder = find_folder(folder) #the file must be valid, not a folder, and folder must be valid if (filename and os.path.basename(filename.strip()) and folder): #this page of the assistant is complete self.set_page_complete(filechooser, True) else: self.set_page_complete(filechooser, False)
def __update_buttons(self, selection): """ What we are trying to detect is the selection or unselection of a row. When a row is unselected, the Open, Rename, and Remove buttons are set insensitive. If a row is selected, the rename and remove buttons are disabled, and the Open button is disabled if the row represents a open database. """ # Get the current selection store, node = selection.get_selected() # if nothing is selected if not node: self.connect.set_sensitive(False) self.rename.set_sensitive(False) self.info.set_sensitive(False) self.rcs.set_sensitive(False) self.repair.set_sensitive(False) self.remove.set_sensitive(False) return path = self.model.get_path(node) if path is None: return is_rev = len(path.get_indices()) > 1 self.rcs.set_label(RCS_BUTTON[is_rev]) if store.get_value(node, ICON_COL) == 'document-open': self.connect.set_sensitive(False) if _RCS_FOUND: self.rcs.set_sensitive(True) else: self.connect.set_sensitive(not is_rev) if _RCS_FOUND and is_rev: self.rcs.set_sensitive(True) else: self.rcs.set_sensitive(False) if store.get_value(node, ICON_COL) == 'dialog-error': path = conv_to_unicode(store.get_value(node, PATH_COL), 'utf8') backup = os.path.join(path, "person.gbkp") self.repair.set_sensitive(os.path.isfile(backup)) else: self.repair.set_sensitive(False) self.rename.set_sensitive(True) self.info.set_sensitive(True) self.remove.set_sensitive(True) self.new.set_sensitive(True)
def __update_buttons(self, selection): """ What we are trying to detect is the selection or unselection of a row. When a row is unselected, the Open, Rename, and Remove buttons are set insensitive. If a row is selected, the rename and remove buttons are disabled, and the Open button is disabled if the row represents a open database. """ # Get the current selection store, node = selection.get_selected() # if nothing is selected if not node: self.connect.set_sensitive(False) self.rename.set_sensitive(False) self.copy.set_sensitive(False) self.rcs.set_sensitive(False) self.repair.set_sensitive(False) self.remove.set_sensitive(False) return path = self.model.get_path(node) if path is None: return is_rev = len(path.get_indices()) > 1 self.rcs.set_label(RCS_BUTTON[is_rev]) if store.get_value(node, ICON_COL) == 'document-open': self.connect.set_sensitive(False) if _RCS_FOUND: self.rcs.set_sensitive(True) else: self.connect.set_sensitive(not is_rev) if _RCS_FOUND and is_rev: self.rcs.set_sensitive(True) else: self.rcs.set_sensitive(False) if store.get_value(node, ICON_COL) == 'dialog-error': path = conv_to_unicode(store.get_value(node, PATH_COL), 'utf8') backup = os.path.join(path, "person.gbkp") self.repair.set_sensitive(os.path.isfile(backup)) else: self.repair.set_sensitive(False) self.rename.set_sensitive(True) self.copy.set_sensitive(True) self.remove.set_sensitive(True) self.new.set_sensitive(True)
def _create_new_db(self, title=None, create_db=True, dbid=None): """ Create a new database, append to model """ new_path, title = self.create_new_db_cli(conv_to_unicode(title, 'utf8'), create_db, dbid) path_name = os.path.join(new_path, NAME_FILE) (tval, last) = time_val(new_path) node = self.model.append(None, [title, new_path, path_name, last, tval, False, '']) self.selection.select_iter(node) path = self.model.get_path(node) self.name_renderer.set_property('editable', True) self.dblist.set_cursor(path, self.column, True) return new_path, title
def _create_new_db(self, title=None, create_db=True, dbid=None): """ Create a new database, append to model """ new_path, title = self.create_new_db_cli( conv_to_unicode(title, 'utf8'), create_db, dbid) path_name = os.path.join(new_path, NAME_FILE) (tval, last) = time_val(new_path) node = self.model.append( None, [title, new_path, path_name, last, tval, False, '']) self.selection.select_iter(node) path = self.model.get_path(node) self.name_renderer.set_property('editable', True) self.dblist.set_cursor(path, self.column, True) return new_path, title
def __really_break_lock(self): """ Deletes the lock file associated with the selected database, then updates the display appropriately. """ try: self.break_lock(self.lock_file) store, node = self.selection.get_selected() dbpath = conv_to_unicode(store.get_value(node, PATH_COL), 'utf8') (tval, last) = time_val(dbpath) store.set_value(node, OPEN_COL, 0) store.set_value(node, ICON_COL, "") store.set_value(node, DATE_COL, last) store.set_value(node, DSORT_COL, tval) except IOError: return
def add_persons_and_families(self): "adds nodes for persons and their families" # variable to communicate with get_person_label self.bUseHtmlOutput = False # The list of families for which we have output the node, # so we don't do it twice families_done = {} for person_handle in self.person_handles: # determine per person if we use HTML style label if self.includeimg: self.bUseHtmlOutput = True person = self.database.get_person_from_handle(person_handle) if person is None: continue p_id = person.get_gramps_id() # Output the person's node label = self.get_person_label(person) (shape, style, color, fill) = self.get_gender_style(person) url = "" if self.includeurl: h = conv_to_unicode(person_handle, 'utf-8') dirpath = "ppl/%s/%s" % (h[-1], h[-2]) dirpath = dirpath.lower() url = "%s/%s.html" % (dirpath, h) self.doc.add_node(p_id, label, shape, color, style, fill, url) # Output families where person is a parent if self.show_families: family_list = person.get_family_handle_list() for fam_handle in family_list: family = self.database.get_family_from_handle(fam_handle) if family is None: continue if fam_handle not in families_done: families_done[fam_handle] = 1 self.__add_family(fam_handle) # If subgraphs are not chosen then each parent is linked # separately to the family. This gives Graphviz greater # control over the layout of the whole graph but # may leave spouses not positioned together. if not self.use_subgraphs: self.doc.add_link(p_id, family.get_gramps_id(), "", self.arrowheadstyle, self.arrowtailstyle)
def select_tilepath(self, *obj): f = Gtk.FileChooserDialog( _("Select tile cache directory for offline mode"), action=Gtk.FileChooserAction.SELECT_FOLDER, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_APPLY, Gtk.ResponseType.OK)) mpath = config.get('geography.path') if not mpath: mpath = HOME_DIR f.set_current_folder(os.path.dirname(mpath)) status = f.run() if status == Gtk.ResponseType.OK: val = conv_to_unicode(f.get_filename()) if val: self.path_entry.set_text(val) f.destroy()
def __handle_export_option(self, value, family_tree_format): """ Handle the "-e" or "--export" option. .. note:: this can only happen in the CLI version. """ if self.gui: return # Need to convert path/filename to unicode before opening # For non latin characters in Windows path/file/user names fname = conv_to_unicode(value, sys.stdin.encoding) if fname == '-': fullpath = '-' else: fullpath = os.path.abspath(os.path.expanduser(fname)) if os.path.exists(fullpath): message = _("WARNING: Output file already exists!\n" "WARNING: It will be overwritten:\n %s" ) % fullpath accepted = self.user.prompt(_('OK to overwrite?'), message, _('yes'), _('no')) if accepted: self.__error(_("Will overwrite the existing file: %s") % fullpath) else: sys.exit(0) if family_tree_format is None: # Guess the file format based on the file extension. # This will get the lower case extension without a period, # or an empty string. family_tree_format = os.path.splitext(fname)[-1][1:].lower() pmgr = BasePluginManager.get_instance() plugin_found = False for plugin in pmgr.get_export_plugins(): if family_tree_format == plugin.get_extension(): plugin_found = True if plugin_found: self.exports.append((fullpath, family_tree_format)) else: self.__error(_("ERROR: Unrecognized format for export file %s") % fname) sys.exit(0)
def __handle_export_option(self, value, family_tree_format): """ Handle the "-e" or "--export" option. .. note:: this can only happen in the CLI version. """ if self.gui: return # Need to convert path/filename to unicode before opening # For non latin characters in Windows path/file/user names fname = conv_to_unicode(value, sys.stdin.encoding) if fname == '-': fullpath = '-' else: fullpath = os.path.abspath(os.path.expanduser(fname)) if os.path.exists(fullpath): message = _( "WARNING: Output file already exists!\n" "WARNING: It will be overwritten:\n %s") % fullpath accepted = self.user.prompt(_('OK to overwrite?'), message, _('yes'), _('no')) if accepted: self.__error( _("Will overwrite the existing file: %s") % fullpath) else: sys.exit(0) if family_tree_format is None: # Guess the file format based on the file extension. # This will get the lower case extension without a period, # or an empty string. family_tree_format = os.path.splitext(fname)[-1][1:].lower() pmgr = BasePluginManager.get_instance() plugin_found = False for plugin in pmgr.get_export_plugins(): if family_tree_format == plugin.get_extension(): plugin_found = True if plugin_found: self.exports.append((fullpath, family_tree_format)) else: self.__error( _("ERROR: Unrecognized format for export file %s") % fname) sys.exit(0)
def add_place_from_kml(self, menu, event, lat, lon): """ Add new place(s) from a kml file 1 - ask for a kml file ? 2 - Read the kml file. 3 - create the place(s) with name and title found in the kml marker. """ # Ask for the kml file filter = Gtk.FileFilter() filter.add_pattern("*.kml") kml = Gtk.FileChooserDialog(_("Select a kml file used to add places"), action=Gtk.FileChooserAction.OPEN, buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Apply'), Gtk.ResponseType.OK)) mpath = HOME_DIR kml.set_current_folder(os.path.dirname(mpath)) kml.set_filter(filter) status = kml.run() if status == Gtk.ResponseType.OK: val = conv_to_unicode(kml.get_filename()) if val: kmlfile = Kml(val) points = kmlfile.add_points() for place in points: (name, coords) = place latlong = coords.pop() (lat, lon) = latlong place_name = PlaceName() place_name.set_value(name) new_place = Place() new_place.set_name(place_name) new_place.set_title(name) new_place.set_latitude(str(lat)) new_place.set_longitude(str(lon)) try: EditPlace(self.dbstate, self.uistate, [], new_place) except WindowActiveError: pass kml.destroy()
def select_tilepath(self, *obj): f = Gtk.FileChooserDialog( _("Select tile cache directory for offline mode"), action=Gtk.FileChooserAction.SELECT_FOLDER, buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Apply'), Gtk.ResponseType.OK)) mpath = config.get('geography.path') if not mpath: mpath = HOME_DIR f.set_current_folder(os.path.dirname(mpath)) status = f.run() if status == Gtk.ResponseType.OK: val = conv_to_unicode(f.get_filename()) if val: self.path_entry.set_text(val) f.destroy()
def add_place_from_kml(self, menu, event, lat, lon): """ Add new place(s) from a kml file 1 - ask for a kml file ? 2 - Read the kml file. 3 - create the place(s) with name and title found in the kml marker. """ # Ask for the kml file filter = Gtk.FileFilter() filter.add_pattern("*.kml") kml = Gtk.FileChooserDialog( _("Select a kml file used to add places"), action=Gtk.FileChooserAction.OPEN, buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Apply'), Gtk.ResponseType.OK)) mpath = HOME_DIR kml.set_current_folder(os.path.dirname(mpath)) kml.set_filter(filter) status = kml.run() if status == Gtk.ResponseType.OK: val = conv_to_unicode(kml.get_filename()) if val: kmlfile = Kml(val) points = kmlfile.add_points() for place in points: (name, coords) = place latlong = coords.pop() (lat, lon) = latlong place_name = PlaceName() place_name.set_value(name) new_place = Place() new_place.set_name(place_name) new_place.set_title(name) new_place.set_latitude(str(lat)) new_place.set_longitude(str(lon)) try: EditPlace(self.dbstate, self.uistate, [], new_place) except WindowActiveError: pass kml.destroy()
def on_write_table(self, obj): f = Gtk.FileChooserDialog(_("Select filename"), parent=self.window, action=Gtk.FileChooserAction.SAVE, buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Save'), Gtk.ResponseType.OK)) f.set_current_folder(get_curr_dir()) status = f.run() f.hide() if status == Gtk.ResponseType.OK: name = conv_to_unicode(f.get_filename()) doc = ODSTab(len(self.row_data)) doc.creator(self.db.get_researcher().get_name()) spreadsheet = TableReport(name, doc) new_titles = [] skip_columns = [] index = 0 for title in self.table_titles: if title == 'sort': skip_columns.append(index) else: new_titles.append(title) index += 1 spreadsheet.initialize(len(new_titles)) spreadsheet.write_table_head(new_titles) index = 0 for top in self.row_data: spreadsheet.set_row(index%2) index += 1 spreadsheet.write_table_data(top,skip_columns) spreadsheet.finalize() f.destroy()
def __copy_db(self, obj): """ Copy the database through low-level file copies. """ # First, get the selected tree: store, node = self.selection.get_selected() # New title: date_string = time.strftime("%d %b %Y %H:%M:%S", time.gmtime()) title = _("%(new_DB_name)s (copied %(date_string)s)") % { 'new_DB_name' : store[node][NAME_COL], 'date_string' : date_string } # Create the row and directory, awaits user edit of title: (new_dir, title) = self._create_new_db(title, create_db=False) # Copy the files: name_file = conv_to_unicode(store[node][FILE_COL], 'utf8') old_dir = os.path.dirname(name_file) for filename in os.listdir(old_dir): if filename == "name.txt": continue old_file = os.path.abspath(os.path.join(old_dir, filename)) shutil.copy2(old_file, new_dir)
def save(self, *obj): """ Callback function called when the save button is pressed. The media object is updated, and callback called. """ description = str(self.description.get_text()) if self.file_text.get_filename() is None: msgstr = _("Import failed") msgstr2 = _("The filename supplied could not be found.") ErrorDialog(msgstr, msgstr2) return filename = conv_to_unicode(self.file_text.get_filename()) full_file = filename if self.relpath.get_active(): pname = str(media_path(self.dbase)) if not os.path.exists(pname): msgstr = _("Cannot import %s") msgstr2 = _("Directory specified in preferences: Base path for relative media paths: %s does not exist. Change preferences or do not use relative path when importing") ErrorDialog(msgstr % filename, msgstr2 % pname) return filename = relative_path(filename, pname) mtype = get_type(full_file) description = description or os.path.basename(filename) self.obj.set_description(description) self.obj.set_mime_type(mtype) name = filename self.obj.set_path(name) self.last_directory = os.path.dirname(full_file) self.relative_path = self.relpath.get_active() self._cleanup_on_exit() if self.callback: self.callback(self.obj)