From 723d8ea1f61186bb9622f29a0aea6ae139802309 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Thu, 28 Apr 2016 00:09:03 -0400 Subject: [PATCH] Add Convert Button to Tree Manager: makes a dbapi from a bsddb --- gramps/gui/dbman.py | 109 ++++++++++++++++++++++++++++++++--- gramps/gui/glade/dbman.glade | 22 ++++++- gramps/gui/viewmanager.py | 21 +++---- 3 files changed, 131 insertions(+), 21 deletions(-) diff --git a/gramps/gui/dbman.py b/gramps/gui/dbman.py index 224dc2d7a..4acecaa8a 100644 --- a/gramps/gui/dbman.py +++ b/gramps/gui/dbman.py @@ -167,7 +167,7 @@ class DbManager(CLIDbManager): self.top.set_transient_for(parent) for attr in ['connect', 'cancel', 'new', 'remove', 'info', - 'dblist', 'rename', 'repair', 'rcs', 'msg']: + 'dblist', 'rename', 'convert', 'repair', 'rcs', 'msg']: setattr(self, attr, self.glade.get_object(attr)) self.model = None @@ -184,6 +184,15 @@ class DbManager(CLIDbManager): self._populate_model() self.before_change = "" self.after_change = "" + self._select_default() + self.user = User(error=ErrorDialog, + callback=self.uistate.pulse_progressbar, + uistate=self.uistate) + + def _select_default(self): + """ + Select the current, or latest, tree. + """ # If already loaded database, center on it: if self._current_node: store, node = self.selection.get_selected() @@ -191,7 +200,6 @@ class DbManager(CLIDbManager): self.selection.select_path(tree_path) self.dblist.scroll_to_cell(tree_path, None, 1, 0.5, 0) - def __connect_signals(self): """ Connects the signals to the buttons on the interface. @@ -206,6 +214,7 @@ class DbManager(CLIDbManager): self.remove.connect('clicked', self.__remove_db) self.new.connect('clicked', self.__new_db) self.rename.connect('clicked', self.__rename_db) + self.convert.connect('clicked', self.__convert_db_ask) self.info.connect('clicked', self.__info_db) self.repair.connect('clicked', self.__repair_db) self.selection.connect('changed', self.__selection_changed) @@ -269,6 +278,7 @@ class DbManager(CLIDbManager): if not node: self.connect.set_sensitive(False) self.rename.set_sensitive(False) + self.convert.set_sensitive(False) self.info.set_sensitive(False) self.rcs.set_sensitive(False) self.repair.set_sensitive(False) @@ -283,10 +293,17 @@ class DbManager(CLIDbManager): self.rcs.set_label(RCS_BUTTON[is_rev]) if store.get_value(node, ICON_COL) == 'document-open': + self.convert.set_sensitive(False) self.connect.set_sensitive(False) if _RCS_FOUND: self.rcs.set_sensitive(True) else: + backend_name = self.get_backend_name_from_dbid("bsddb") + if (store.get_value(node, ICON_COL) in [None, ""] and + store.get_value(node, BACKEND_COL).startswith(backend_name)): + self.convert.set_sensitive(True) + else: + self.convert.set_sensitive(False) self.connect.set_sensitive(not is_rev) if _RCS_FOUND and is_rev: self.rcs.set_sensitive(True) @@ -380,18 +397,26 @@ class DbManager(CLIDbManager): self.model = Gtk.TreeStore(str, str, str, str, int, bool, str, str) #use current names to set up the model + self._current_node = None + last_accessed_node = None + last_accessed = 0 for items in self.current_names: data = list(items[:8]) - backend_type = self.get_backend_name_from_dbid(data[7]) + backend_type = self.get_backend_name_from_dbid(data[BACKEND_COL]) version = str(".".join([str(v) for v in items[8]])) node = self.model.append(None, data[:-1] + [backend_type + ", " + version]) # For already loaded database, set current_node: if self.dbstate.db and self.dbstate.db.get_save_path() == data[1]: self._current_node = node + if data[DSORT_COL] > last_accessed: + last_accessed = data[DSORT_COL] + last_accessed_node = node for rdata in find_revisions(os.path.join(items[1], ARCHIVE_V)): data = [rdata[2], rdata[0], items[1], rdata[1], 0, False, "", backend_type + ", " + version] self.model.append(node, data) + if self._current_node is None: + self._current_node = last_accessed_node self.model.set_sort_column_id(NAME_COL, Gtk.SortType.ASCENDING) self.dblist.set_model(self.model) @@ -470,7 +495,7 @@ class DbManager(CLIDbManager): dbpath = store.get_value(node, PATH_COL) (tval, last) = time_val(dbpath) store.set_value(node, OPEN_COL, 0) - store.set_value(node, ICON_COL, "") + store.set_value(node, ICON_COL, "") # see bug_fix store.set_value(node, DATE_COL, last) store.set_value(node, DSORT_COL, tval) except IOError: @@ -488,6 +513,7 @@ class DbManager(CLIDbManager): """ self.connect.set_sensitive(False) self.rename.set_sensitive(False) + self.convert.set_sensitive(False) self.info.set_sensitive(False) self.rcs.set_sensitive(False) self.repair.set_sensitive(False) @@ -507,7 +533,7 @@ class DbManager(CLIDbManager): if len(new_text) > 0: node = self.model.get_iter(path) old_text = self.model.get_value(node, NAME_COL) - if self.model.get_value(node, ICON_COL) != None: + if self.model.get_value(node, ICON_COL) not in [None, ""]: # this database is loaded. We must change the title # in case we change the name several times before quitting, # we save the first old name. @@ -596,7 +622,7 @@ class DbManager(CLIDbManager): else: base_path = self.dbstate.db.get_save_path() archive = os.path.join(base_path, ARCHIVE) - check_in(self.dbstate.db, archive, User(), self.__start_cursor) + check_in(self.dbstate.db, archive, self.user, self.__start_cursor) self.__end_cursor() self.__populate() @@ -614,7 +640,7 @@ class DbManager(CLIDbManager): dbase.load(new_path, None) self.__start_cursor(_("Importing archive...")) - check_out(dbase, revision, db_path, User()) + check_out(dbase, revision, db_path, self.user) self.__end_cursor() dbase.close() @@ -706,6 +732,73 @@ class DbManager(CLIDbManager): # rebuild the display self.__populate() + def __convert_db_ask(self, obj): + """ + Ask to convert a closed BSDDB tree into a new DB-API + tree. + """ + store, node = self.selection.get_selected() + name = store[node][0] + dirname = store[node][1] + db = self.dbstate.open_database(name) + if db: + QuestionDialog( + _("Convert the '%s' database?") % name, + _("You wish to convert this database into the new DB-API format?"), + _("Convert"), + lambda: self.__convert_db(name, dirname, db), self.top) + else: + ErrorDialog( + _("Opening the '%s' database") % name, + _("An attempt to open the database failed.")) + + def __convert_db(self, name, dirname, db): + """ + Actually convert the db from BSDDB to DB-API. + """ + plugin_manager = GuiPluginManager.get_instance() + export_function = None + for plugin in plugin_manager.get_export_plugins(): + if plugin.get_extension() == "gramps": + export_function = plugin.get_export_function() + break + ## Next, get an XML dump: + if export_function is None: + ErrorDialog( + _("Converting the '%s' database") % name, + _("An attempt to export the database failed.")) + db.close() + return + self.__start_cursor(_("Converting data...")) + xml_file = os.path.join(dirname, "backup.gramps") + export_function(db, xml_file, self.user) + db.close() + count = 1 + new_text = "%s %s" % (name, _("(Converted #%d)") % count) + while self.existing_name(new_text): + count += 1 + new_text = "%s %s" % (name, _("(Converted #%d)") % count) + new_path, newname = self._create_new_db(new_text) + ## Create a new database of correct type: + dbase = self.dbstate.make_database("dbapi") + dbase.write_version(new_path) + dbase.load(new_path) + ## import from XML + import_function = None + for plugin in plugin_manager.get_import_plugins(): + if plugin.get_extension() == "gramps": + import_function = plugin.get_import_function() + if import_function is None: + ErrorDialog( + _("Converting the '%s' database") % name, + _("An attempt to import into the database failed.")) + else: + import_function(dbase, xml_file, self.user) + self.__end_cursor() + dbase.close() + self.__populate() + self._select_default() + def __rename_db(self, obj): """ Start the rename process by calling the start_editing option on @@ -875,7 +968,7 @@ class DbManager(CLIDbManager): if drag_value and urlparse(drag_value).scheme != "": fname, title = [], [] for treename in [v.strip() for v in drag_value.split("\n") if v.strip() != '']: - f, t = self.import_new_db(treename, User()) + f, t = self.import_new_db(treename, self.user) fname.append(f) title.append(t) return fname, title diff --git a/gramps/gui/glade/dbman.glade b/gramps/gui/glade/dbman.glade index 39b585eed..44316fafc 100644 --- a/gramps/gui/glade/dbman.glade +++ b/gramps/gui/glade/dbman.glade @@ -107,7 +107,7 @@ Family Trees - Gramps center-on-parent 800 - 300 + 350 dialog @@ -299,6 +299,22 @@ 3 + + + Con_vert + False + True + True + True + False + True + + + False + False + 4 + + Re_pair @@ -312,7 +328,7 @@ False False - 4 + 5 @@ -328,7 +344,7 @@ False False - 5 + 6 diff --git a/gramps/gui/viewmanager.py b/gramps/gui/viewmanager.py index b9b2804f9..dd04c28ad 100644 --- a/gramps/gui/viewmanager.py +++ b/gramps/gui/viewmanager.py @@ -1104,16 +1104,17 @@ class ViewManager(CLIManager): if dialog.after_change != "": # We change the title of the main window. old_title = self.uistate.window.get_title() - delim = old_title.find(' - ') - tit1 = old_title[:delim] - tit2 = old_title[delim:] - if '<=' in tit2: - delim2 = tit2.find('<=') + 3 - tit3 = tit2[delim2:-1] - new_title = dialog.after_change + tit2.replace(']', '') + ' => ' + tit1 + ']' - else: - new_title = dialog.after_change + tit2 + ' <= [' + tit1 + ']' - self.uistate.window.set_title(new_title) + if old_title: + delim = old_title.find(' - ') + tit1 = old_title[:delim] + tit2 = old_title[delim:] + if '<=' in tit2: + delim2 = tit2.find('<=') + 3 + tit3 = tit2[delim2:-1] + new_title = dialog.after_change + tit2.replace(']', '') + ' => ' + tit1 + ']' + else: + new_title = dialog.after_change + tit2 + ' <= [' + tit1 + ']' + self.uistate.window.set_title(new_title) def __post_load(self): """