def start(self): from bauble.plugins.garden.accession import Accession sub_editor = None if self.session.query(Accession).count() == 0: msg = 'You must first add or import at least one Accession into '\ 'the database before you can add plants.\n\nWould you like '\ 'to open the Accession editor?' if utils.yes_no_dialog(msg): # cleanup in case we start a new PlantEditor self.presenter.cleanup() from bauble.plugins.garden.accession import AccessionEditor sub_editor = AccessionEditor() self._commited = sub_editor.start() if self.session.query(Location).count() == 0: msg = 'You must first add or import at least one Location into '\ 'the database before you can add species.\n\nWould you '\ 'like to open the Location editor?' if utils.yes_no_dialog(msg): # cleanup in case we start a new PlantEditor self.presenter.cleanup() sub_editor = LocationEditor() self._commited = sub_editor.start() if self.branched_plant: # set title if in branch mode title = self.presenter.view.get_window().props.title self.presenter.view.get_window().props.title += \ utils.utf8(' - %s' % _('Branch Mode')) message_box_parent = self.presenter.view.widgets.message_box_parent map(message_box_parent.remove, message_box_parent.get_children()) msg = _('Branching from %(plant_code)s. The quantity will ' 'be subtracted from %(plant_code)s') \ % {'plant_code': str(self.branched_plant)} box = utils.add_message_box(message_box_parent, utils.MESSAGE_BOX_INFO) box.message = msg box.show_all() # don't allow editing the accession code in a branched plant self.presenter.view.widgets.plant_acc_entry.props.editable = False if not sub_editor: while True: response = self.presenter.start() self.presenter.view.save_state() if self.handle_response(response): break self.session.close() # cleanup session self.presenter.cleanup() return self._committed
def __export_task(self, path): # if not os.path.exists(path): # raise ValueError("CSVExporter: path does not exist.\n" + path) filename_template = os.path.join(path, "%s.txt") # timeout = tasklet.WaitForTimeout(12) steps_so_far = 0 ntables = 0 for table in db.metadata.sorted_tables: ntables += 1 filename = filename_template % table.name if os.path.exists(filename): msg = _( "Export file <b>%(filename)s</b> for " "<b>%(table)s</b> table already exists.\n\n<i>Would " "you like to continue?</i>" ) % {"filename": filename, "table": table.name} if utils.yes_no_dialog(msg): return def replace(s): if isinstance(s, (str, unicode)): s.replace("\n", "\\n") return s def write_csv(filename, rows): f = open(filename, "wb") writer = UnicodeWriter(f, quotechar=QUOTE_CHAR, quoting=QUOTE_STYLE) writer.writerows(rows) f.close() update_every = 30 for table in db.metadata.sorted_tables: filename = filename_template % table.name steps_so_far += 1 fraction = float(steps_so_far) / float(ntables) pb_set_fraction(fraction) msg = _("exporting %(table)s table to %(filename)s") % {"table": table.name, "filename": filename} bauble.task.set_message(msg) logger.info("exporting %s" % table.name) # get the data results = table.select().execute().fetchall() # create empty files with only the column names if len(results) == 0: write_csv(filename, [table.c.keys()]) yield continue rows = [] rows.append(table.c.keys()) # append col names ctr = 0 for row in results: values = map(replace, row.values()) rows.append(values) if ctr == update_every: yield ctr = 0 ctr += 1 write_csv(filename, rows)
def remove_callback(families): """ The callback function to remove a family from the family context menu. """ family = families[0] from bauble.plugins.plants.genus import Genus session = db.Session() ngen = session.query(Genus).filter_by(family_id=family.id).count() safe_str = utils.xml_safe_utf8(str(family)) if ngen > 0: msg = _('The family <i>%(family)s</i> has %(num_genera)s genera. Are ' 'you sure you want to remove it?') % dict(family=safe_str, num_genera=ngen) else: msg = _("Are you sure you want to remove the family <i>%s</i>?") \ % safe_str if not utils.yes_no_dialog(msg): return try: obj = session.query(Family).get(family.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe_utf8(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def remove_callback(values): """ The callback function to remove a species from the species context menu. """ from bauble.plugins.garden.accession import Accession session = db.Session() species = values[0] if isinstance(species, VernacularName): species = species.species nacc = session.query(Accession).filter_by(species_id=species.id).count() safe_str = utils.xml_safe(str(species)) if nacc > 0: msg = _('The species <i>%(species)s</i> has %(num_accessions)s ' 'accessions. Are you sure you want remove it?') \ % dict(species=safe_str, num_accessions=nacc) else: msg = _("Are you sure you want to remove the species <i>%s</i>?") \ % safe_str if not utils.yes_no_dialog(msg): return try: obj = session.query(Species).get(species.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def start(self, filename=None, plants=None): if filename == None: # no filename, ask the user d = gtk.FileChooserDialog(_("Choose a file to export to..."), None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) response = d.run() filename = d.get_filename() d.destroy() if response != gtk.RESPONSE_ACCEPT or filename == None: return if plants: nplants = len(plants) else: nplants = db.Session().query(Plant).count() if nplants > 3000: msg = _('You are exporting %(nplants)s plants to ABCD format. ' \ 'Exporting this many plants may take several minutes. '\ '\n\n<i>Would you like to continue?</i>') \ % ({'nplants': nplants}) if not utils.yes_no_dialog(msg): return self.run(filename, plants)
def remove_callback(values): """ The callback function to remove a species from the species context menu. """ from bauble.plugins.garden.accession import Accession session = db.Session() species = values[0] if isinstance(species, VernacularName): species = species.species nacc = session.query(Accession).filter_by(species_id=species.id).count() safe_str = utils.xml_safe(str(species)) if nacc > 0: msg = _( "The species <i>%(species)s</i> has %(num_accessions)s " "accessions. Are you sure you want remove it?" ) % dict(species=safe_str, num_accessions=nacc) else: msg = _("Are you sure you want to remove the species <i>%s</i>?") % safe_str if not utils.yes_no_dialog(msg): return try: obj = session.query(Species).get(species.id) session.delete(obj) session.commit() except Exception, e: msg = _("Could not delete.\n\n%s") % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def on_remove_button_clicked(self, button, data=None): """ Removes the currently selected vernacular name from the view. """ tree = self.view.widgets.vern_treeview path, col = tree.get_cursor() treemodel = tree.get_model() vn = treemodel[path][0] msg = _('Are you sure you want to remove the vernacular ' 'name <b>%s</b>?') % utils.xml_safe(vn.name) if vn.name and not vn in self.session.new and not \ utils.yes_no_dialog(msg, parent=self.view.get_window()): return treemodel.remove(treemodel.get_iter(path)) self.model.vernacular_names.remove(vn) utils.delete_or_expunge(vn) if not self.model.default_vernacular_name: # if there is only one value in the tree then set it as the # default vernacular name first = treemodel.get_iter_first() if first: # self.set_model_attr('default_vernacular_name', # tree_model[first][0]) self.model.default_vernacular_name = treemodel[first][0] self.parent_ref().refresh_sensitivity() self._dirty = True
def remove_callback(families): """ The callback function to remove a family from the family context menu. """ family = families[0] from bauble.plugins.plants.genus import Genus session = db.Session() ngen = session.query(Genus).filter_by(family_id=family.id).count() safe_str = utils.xml_safe(str(family)) if ngen > 0: msg = _('The family <i>%(family)s</i> has %(num_genera)s genera. Are ' 'you sure you want to remove it?') % dict(family=safe_str, num_genera=ngen) else: msg = _("Are you sure you want to remove the family <i>%s</i>?") \ % safe_str if not utils.yes_no_dialog(msg): return try: obj = session.query(Family).get(family.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def on_key_released(self, widget, event): ''' if the user hits the delete key on a selected tag in the tag editor then delete the tag ''' keyname = gtk.gdk.keyval_name(event.keyval) if keyname != "Delete": return model, row_iter = self.tag_tree.get_selection().get_selected() tag_name = model[row_iter][1] msg = _('Are you sure you want to delete the tag "%s"?') % tag_name if not utils.yes_no_dialog(msg): return session = db.Session() try: query = session.query(Tag) tag = query.filter_by(tag=unicode(tag_name)).one() session.delete(tag) session.commit() model.remove(row_iter) _reset_tags_menu() view = bauble.gui.get_view() if hasattr(view, 'update'): view.update() except Exception, e: utils.message_details_dialog(utils.xml_safe(str(e)), traceback.format_exc(), gtk.MESSAGE_ERROR)
def remove_callback(genera): """ The callback function to remove a genus from the genus context menu. """ genus = genera[0] from bauble.plugins.plants.species_model import Species session = db.Session() nsp = session.query(Species).filter_by(genus_id=genus.id).count() safe_str = utils.xml_safe(str(genus)) if nsp > 0: msg = (_('The genus <i>%(genus)s</i> has %(num_species)s species. ' 'Are you sure you want to remove it?') % dict(genus=safe_str, num_species=nsp)) else: msg = (_("Are you sure you want to remove the genus <i>%s</i>?") % safe_str) if not utils.yes_no_dialog(msg): return try: obj = session.query(Genus).get(genus.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def on_remove_button_clicked(self, button, data=None): """ removes the currently selected synonym from the list of synonyms for this species """ # TODO: maybe we should only ask 'are you sure' if the selected value # is an instance, this means it will be deleted from the database tree = self.view.widgets.fam_syn_treeview path, col = tree.get_cursor() tree_model = tree.get_model() value = tree_model[tree_model.get_iter(path)][0] # debug('%s: %s' % (value, type(value))) s = Family.str(value.synonym) msg = ( "Are you sure you want to remove %s as a synonym to the " "current family?\n\n<i>Note: This will not remove the family " "%s from the database.</i>" % (s, s) ) if utils.yes_no_dialog(msg, parent=self.view.get_window()): tree_model.remove(tree_model.get_iter(path)) self.model.synonyms.remove(value.synonym) utils.delete_or_expunge(value) self.session.flush([value]) self._dirty = True self.refresh_sensitivity()
def init(force=False): """ Initialize the plugin manager. 1. Check for and install any plugins in the plugins dict that aren't in the registry. 2. Call each init() for each plugin the registry in order of dependency 3. Register the command handlers in the plugin's commands[] NOTE: This should be called after after Bauble has established a connection to a database with db.open() """ logger.debug('bauble.pluginmgr.init()') # ****** # NOTE: Be careful not to keep any references to # PluginRegistry open here as it will cause a deadlock if you try # to create a new database. For example, don't query the # PluginRegistry with a session without closing the session. # ****** # search for plugins that are in the plugins dict but not in the registry registered = plugins.values() logger.debug('registered plugins: %s' % plugins) try: # try to access the plugin registry, if the table does not exist # then it might mean that we are opening a pre 0.9 database, in this # case we just assume all the plugins have been installed and # registered, this might be the right thing to do but at least it # allows you to connect to a pre bauble 0.9 database and use it to # upgrade to a >=0.9 database registered_names = PluginRegistry.names() not_installed = [ p for n, p in plugins.iteritems() if n not in registered_names ] if len(not_installed) > 0: msg = _('The following plugins were not found in the plugin ' 'registry:\n\n<b>%s</b>\n\n' '<i>Would you like to install them now?</i>' % ', '.join([p.__class__.__name__ for p in not_installed])) if force or utils.yes_no_dialog(msg): install([p for p in not_installed]) # sort plugins in the registry by their dependencies not_registered = [] for name in PluginRegistry.names(): try: registered.append(plugins[name]) except KeyError, e: logger.debug("could not find '%s' plugin. " "removing from database" % e) not_registered.append(utils.utf8(name)) PluginRegistry.remove(name=name) if not_registered: msg = _('The following plugins are in the registry but ' 'could not be loaded:\n\n%(plugins)s' % {'plugins': utils.utf8(', '.join(sorted(not_registered)))}) utils.message_dialog(utils.xml_safe(msg), type=gtk.MESSAGE_WARNING)
def __export_task(self, path): filename_template = os.path.join(path, "%s.txt") steps_so_far = 0 ntables = 0 for table in db.metadata.sorted_tables: ntables += 1 filename = filename_template % table.name if os.path.exists(filename): msg = _('Export file <b>%(filename)s</b> for ' '<b>%(table)s</b> table already exists.\n\n<i>Would ' 'you like to continue?</i>')\ % {'filename': filename, 'table': table.name} if utils.yes_no_dialog(msg): return def replace(s): if isinstance(s, (str, unicode)): s.replace('\n', '\\n') return s def write_csv(filename, rows): f = open(filename, 'wb') writer = UnicodeWriter(f, quotechar=QUOTE_CHAR, quoting=QUOTE_STYLE) writer.writerows(rows) f.close() update_every = 30 for table in db.metadata.sorted_tables: filename = filename_template % table.name steps_so_far += 1 fraction = float(steps_so_far) / float(ntables) pb_set_fraction(fraction) msg = _('exporting %(table)s table to %(filename)s')\ % {'table': table.name, 'filename': filename} bauble.task.set_message(msg) logger.info("exporting %s" % table.name) # get the data results = table.select().execute().fetchall() # create empty files with only the column names if len(results) == 0: write_csv(filename, [table.c.keys()]) yield continue rows = [] rows.append(table.c.keys()) # append col names ctr = 0 for row in results: values = map(replace, row.values()) rows.append(values) if ctr == update_every: yield ctr = 0 ctr += 1 write_csv(filename, rows)
def __export_task(self, path): filename_template = os.path.join(path, "%s.txt") steps_so_far = 0 ntables = 0 for table in db.metadata.sorted_tables: ntables += 1 filename = filename_template % table.name if os.path.exists(filename): msg = _('Export file <b>%(filename)s</b> for ' '<b>%(table)s</b> table already exists.\n\n<i>Would ' 'you like to continue?</i>')\ % {'filename': filename, 'table': table.name} if utils.yes_no_dialog(msg): return def replace(s): if isinstance(s, (str, unicode)): s.replace('\n', '\\n') return s def write_csv(filename, rows): f = open(filename, 'wb') writer = UnicodeWriter(f, quotechar=QUOTE_CHAR, quoting=QUOTE_STYLE) writer.writerows(rows) f.close() update_every = 30 for table in db.metadata.sorted_tables: filename = filename_template % table.name steps_so_far += 1 fraction = float(steps_so_far)/float(ntables) pb_set_fraction(fraction) msg = _('exporting %(table)s table to %(filename)s')\ % {'table': table.name, 'filename': filename} bauble.task.set_message(msg) logger.info("exporting %s" % table.name) # get the data results = table.select().execute().fetchall() # create empty files with only the column names if len(results) == 0: write_csv(filename, [table.c.keys()]) yield continue rows = [] rows.append(table.c.keys()) # append col names ctr = 0 for row in results: values = map(replace, row.values()) rows.append(values) if ctr == update_every: yield ctr = 0 ctr += 1 write_csv(filename, rows)
def init(force=False): """ Initialize the plugin manager. 1. Check for and install any plugins in the plugins dict that aren't in the registry. 2. Call each init() for each plugin the registry in order of dependency 3. Register the command handlers in the plugin's commands[] NOTE: This is called after after Ghini has created the GUI and established a connection to a database with db.open() """ logger.debug('bauble.pluginmgr.init()') # ****** # NOTE: Be careful not to keep any references to # PluginRegistry open here as it will cause a deadlock if you try # to create a new database. For example, don't query the # PluginRegistry with a session without closing the session. # ****** # search for plugins that are in the plugins dict but not in the registry registered = plugins.values() logger.debug('registered plugins: %s' % plugins) try: # try to access the plugin registry, if the table does not exist # then it might mean that we are opening a pre 0.9 database, in this # case we just assume all the plugins have been installed and # registered, this might be the right thing to do but at least it # allows you to connect to a pre bauble 0.9 database and use it to # upgrade to a >=0.9 database registered_names = PluginRegistry.names() not_installed = [p for n, p in plugins.iteritems() if n not in registered_names] if len(not_installed) > 0: msg = _('The following plugins were not found in the plugin ' 'registry:\n\n<b>%s</b>\n\n' '<i>Would you like to install them now?</i>') % \ ', '.join([p.__class__.__name__ for p in not_installed]) if force or utils.yes_no_dialog(msg): install([p for p in not_installed]) # sort plugins in the registry by their dependencies not_registered = [] for name in PluginRegistry.names(): try: registered.append(plugins[name]) except KeyError, e: logger.debug("could not find '%s' plugin. " "removing from database" % e) not_registered.append(utils.utf8(name)) PluginRegistry.remove(name=name) if not_registered: msg = _('The following plugins are in the registry but ' 'could not be loaded:\n\n%(plugins)s') % \ {'plugins': utils.utf8(', '.join(sorted(not_registered)))} utils.message_dialog(utils.xml_safe(msg), type=gtk.MESSAGE_WARNING)
def on_delete_event(self, *args): import bauble.task as task if task.running(): msg = _('Would you like the cancel the current tasks?') if not utils.yes_no_dialog(msg): # stop other handlers for being invoked for this event return True task.kill() return False
def on_changed_name_combo(self, combo, data=None): """ the name changed so fill in everything else """ name = combo.get_active_text() if name is None: return conn_list = prefs.prefs[bauble.conn_list_pref] if self.current_name is not None: ## we are leaving some valid settings if self.current_name not in conn_list: msg = _("Do you want to save %s?") % self.current_name if utils.yes_no_dialog(msg): self.save_current_to_prefs() else: self.remove_connection(self.current_name) # combo.set_active_iter(active_iter) self.current_name = None elif not self.compare_prefs_to_saved(self.current_name): msg = (_("Do you want to save your changes to %s ?") % self.current_name) if utils.yes_no_dialog(msg): self.save_current_to_prefs() if conn_list is not None and name in conn_list: ## we are retrieving connection info from the global settings if conn_list[name]['type'] not in self._dbtypes: # in case the connection type has changed or isn't supported # on this computer self.type_combo.set_active(-1) self.type_combo.emit("changed") # in case 0 was already active else: self.type_combo.set_active(0) self.type_combo.set_active(self._dbtypes. index(conn_list[name]["type"])) self.params_box.refresh_view(conn_list[name]) else: # this is for new connections self.type_combo.set_active(0) self.type_combo.emit("changed") # in case 0 was already active self.current_name = name self.old_params.clear()
def on_changed_name_combo(self, combo, data=None): """ the name changed so fill in everything else """ name = combo.get_active_text() if name is None: return conn_list = prefs.prefs[bauble.conn_list_pref] if self.current_name is not None: ## we are leaving some valid settings if self.current_name not in conn_list: msg = _("Do you want to save %s?") % self.current_name if utils.yes_no_dialog(msg): self.save_current_to_prefs() else: self.remove_connection(self.current_name) # combo.set_active_iter(active_iter) self.current_name = None elif not self.compare_prefs_to_saved(self.current_name): msg = (_("Do you want to save your changes to %s ?") % self.current_name) if utils.yes_no_dialog(msg): self.save_current_to_prefs() if conn_list is not None and name in conn_list: ## we are retrieving connection info from the global settings if conn_list[name]['type'] not in self._dbtypes: # in case the connection type has changed or isn't supported # on this computer self.type_combo.set_active(-1) self.type_combo.emit("changed") # in case 0 was already active else: self.type_combo.set_active(0) self.type_combo.set_active( self._dbtypes.index(conn_list[name]["type"])) self.params_box.refresh_view(conn_list[name]) else: # this is for new connections self.type_combo.set_active(0) self.type_combo.emit("changed") # in case 0 was already active self.current_name = name self.old_params.clear()
def start(cls): """ Start the CSV importer. This tool will also reinitialize the plugins after importing. """ msg = _('It is possible that importing data into this database could '\ 'destroy or corrupt your existing data.\n\n<i>Would you '\ 'like to continue?</i>') if utils.yes_no_dialog(msg): c = CSVImporter() c.start()
def start(cls): """ Start the CSV importer. This tool will also reinitialize the plugins after importing. """ msg = _('It is possible that importing data into this database could ' 'destroy or corrupt your existing data.\n\n<i>Would you ' 'like to continue?</i>') if utils.yes_no_dialog(msg): c = CSVImporter() c.start()
def on_dialog_response(self, dialog, response, data=None): """ The dialog's response signal handler. """ self._error = False if response == gtk.RESPONSE_OK: settings = self.params_box.get_prefs() dbtype = self.widgets.type_combo.get_active_text() if dbtype == 'SQLite': filename = settings['file'] if not os.path.exists(filename): path, f = os.path.split(filename) if not os.access(path, os.R_OK): self._error = True msg = _("Bauble does not have permission to " "read the directory:\n\n%s") % path utils.message_dialog(msg, gtk.MESSAGE_ERROR) elif not os.access(path, os.W_OK): self._error = True msg = _("Bauble does not have permission to " "write to the directory:\n\n%s") % path utils.message_dialog(msg, gtk.MESSAGE_ERROR) elif not os.access(filename, os.R_OK): self._error = True msg = _("Bauble does not have permission to read the " "database file:\n\n%s") % filename utils.message_dialog(msg, gtk.MESSAGE_ERROR) elif not os.access(filename, os.W_OK): self._error = True msg = _("Bauble does not have permission to " "write to the database file:\n\n%s") % filename utils.message_dialog(msg, gtk.MESSAGE_ERROR) if not self._error: self.save_current_to_prefs() prefs.prefs[prefs.picture_root_pref] = settings.get( 'pictures', '') elif response == gtk.RESPONSE_CANCEL or \ response == gtk.RESPONSE_DELETE_EVENT: if not self.compare_prefs_to_saved(self.current_name): msg = _("Do you want to save your changes?") if utils.yes_no_dialog(msg): self.save_current_to_prefs() # system-defined GtkDialog responses are always negative, in which # case we want to hide it if response < 0: dialog.hide() #dialog.emit_stop_by_name('response') return response
def source_detail_remove_callback(details): detail = details[0] s = "%s: %s" % (detail.__class__.__name__, str(detail)) msg = _("Are you sure you want to remove %s?") % utils.xml_safe(s) if not utils.yes_no_dialog(msg): return try: session = db.Session() obj = session.query(SourceDetail).get(detail.id) session.delete(obj) session.commit() except Exception, e: msg = _("Could not delete.\n\n%s") % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def on_remove_button_clicked(self, button, data=None): """ remove the connection from connection list, this does not affect the database or its data """ msg = (_('Are you sure you want to remove "%s"?\n\n' '<i>Note: This only removes the connection to the database ' 'and does not affect the database or its data</i>') % self.current_name) if not utils.yes_no_dialog(msg): return self.current_name = None self.remove_connection(self.name_combo.get_active_text()) self.name_combo.set_active(0)
def on_remove_button_clicked(self, button, *args): """ """ user = self.get_selected_user() msg = _( "Are you sure you want to remove user <b>%(name)s</b>?\n\n" "<i>It is possible that this user could have permissions " "on other databases not related to Ghini.</i>" ) % {"name": user} if not utils.yes_no_dialog(msg): return try: drop(user, revoke=True) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
def on_remove_button_clicked(self, button, *args): """ """ user = self.get_selected_user() msg = _('Are you sure you want to remove user <b>%(name)s</b>?\n\n' '<i>It is possible that this user could have permissions ' 'on other databases not related to Bauble.</i>') \ % {'name': user} if not utils.yes_no_dialog(msg): return try: drop(user, revoke=True) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
def source_detail_remove_callback(details): detail = details[0] s = '%s: %s' % (detail.__class__.__name__, str(detail)) msg = _("Are you sure you want to remove %s?") % utils.xml_safe(s) if not utils.yes_no_dialog(msg): return try: session = db.Session() obj = session.query(SourceDetail).get(detail.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def on_remove_button_clicked(self, button, data=None): """ removes the currently selected synonym from the list of synonyms for this species """ # TODO: maybe we should only ask 'are you sure' if the selected value # is an instance, this means it will be deleted from the database tree = self.view.widgets.sp_syn_treeview path, col = tree.get_cursor() tree_model = tree.get_model() value = tree_model[tree_model.get_iter(path)][0] s = Species.str(value.synonym, markup=True) msg = ( "Are you sure you want to remove %s as a synonym to the " "current species?\n\n<i>Note: This will not remove the species " "%s from the database.</i>" % (s, s) ) if not utils.yes_no_dialog(msg, parent=self.view.get_window()): return tree_model.remove(tree_model.get_iter(path)) self.model.synonyms.remove(value.synonym) utils.delete_or_expunge(value) # TODO: ** important ** this doesn't respect any unique # contraints on the species for synonyms and allow a # species to have another species as a synonym multiple # times...see below # TODO: using session.flush here with an argument is # deprecated in SA 0.5 and will probably removed in SA # 0.6...but how do we only flush the one value..unless we # create a new session, merge it, commit that session, # close it and then refresh the same object in # self.session # make the change in synonym immediately available so that if # we try to add the same species again we don't break the # SpeciesSynonym UniqueConstraint # tmp_session = db.Session() # tmp_value = tmp.session.merge(value) # tmp.session.commit() # tmp.session.close() # self.session.refresh(value) # self.session.flush([value]) self._dirty = True self.parent_ref().refresh_sensitivity()
def on_remove_button_clicked(self, button, data=None): ''' removes the currently selected synonym from the list of synonyms for this species ''' # TODO: maybe we should only ask 'are you sure' if the selected value # is an instance, this means it will be deleted from the database tree = self.view.widgets.sp_syn_treeview path, col = tree.get_cursor() tree_model = tree.get_model() value = tree_model[tree_model.get_iter(path)][0] s = Species.str(value.synonym, markup=True) msg = 'Are you sure you want to remove %s as a synonym to the ' \ 'current species?\n\n<i>Note: This will not remove the species '\ '%s from the database.</i>' % (s, s) if not utils.yes_no_dialog(msg, parent=self.view.get_window()): return tree_model.remove(tree_model.get_iter(path)) self.model.synonyms.remove(value.synonym) utils.delete_or_expunge(value) # TODO: ** important ** this doesn't respect any unique # contraints on the species for synonyms and allow a # species to have another species as a synonym multiple # times...see below # TODO: using session.flush here with an argument is # deprecated in SA 0.5 and will probably removed in SA # 0.6...but how do we only flush the one value..unless we # create a new session, merge it, commit that session, # close it and then refresh the same object in # self.session # make the change in synonym immediately available so that if # we try to add the same species again we don't break the # SpeciesSynonym UniqueConstraint # tmp_session = db.Session() # tmp_value = tmp.session.merge(value) # tmp.session.commit() # tmp.session.close() # self.session.refresh(value) #self.session.flush([value]) self._dirty = True self.parent_ref().refresh_sensitivity()
def remove_callback(locations): loc = locations[0] s = "%s: %s" % (loc.__class__.__name__, str(loc)) if len(loc.plants) > 0: msg = _("Please remove the plants from <b>%(location)s</b> " "before deleting it.") % {"location": loc} utils.message_dialog(msg, gtk.MESSAGE_WARNING) return msg = _("Are you sure you want to remove %s?") % utils.xml_safe(s) if not utils.yes_no_dialog(msg): return try: session = db.Session() obj = session.query(Location).get(loc.id) session.delete(obj) session.commit() except Exception, e: msg = _("Could not delete.\n\n%s") % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def remove_callback(plants): s = ', '.join([str(p) for p in plants]) msg = _("Are you sure you want to remove the following plants?\n\n%s") \ % utils.xml_safe_utf8(s) if not utils.yes_no_dialog(msg): return session = db.Session() for plant in plants: obj = session.query(Plant).get(plant.id) session.delete(obj) try: session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe_utf8(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def remove_callback(tags): """ :param tags: a list of :class:`Tag` objects. """ tag = tags[0] s = '%s: %s' % (tag.__class__.__name__, utils.xml_safe(tag)) msg = _("Are you sure you want to remove %s?") % s if not utils.yes_no_dialog(msg): return session = db.Session() try: obj = session.query(Tag).get(tag.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def remove_callback(tags): """ :param tags: a list of :class:`Tag` objects. """ tag = tags[0] s = '%s: %s' % (tag.__class__.__name__, utils.xml_safe(tag)) msg = _("Are you sure you want to remove %s?") % s if not utils.yes_no_dialog(msg): return session = object_session(tag) try: obj = session.query(Tag).get(tag.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def remove_callback(locations): loc = locations[0] s = '%s: %s' % (loc.__class__.__name__, str(loc)) if len(loc.plants) > 0: msg = _('Please remove the plants from <b>%(location)s</b> ' 'before deleting it.') % {'location': loc} utils.message_dialog(msg, gtk.MESSAGE_WARNING) return msg = _("Are you sure you want to remove %s?") % \ utils.xml_safe(s) if not utils.yes_no_dialog(msg): return try: session = db.Session() obj = session.query(Location).get(loc.id) session.delete(obj) session.commit() except Exception, e: msg = _('Could not delete.\n\n%s') % utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
def on_remove_button_clicked(self, button, data=None): ''' removes the currently selected synonym from the list of synonyms for this species ''' # TODO: maybe we should only ask 'are you sure' if the selected value # is an instance, this means it will be deleted from the database tree = self.view.widgets.gen_syn_treeview path, col = tree.get_cursor() tree_model = tree.get_model() value = tree_model[tree_model.get_iter(path)][0] s = Genus.str(value.synonym) msg = _('Are you sure you want to remove %(genus)s as a synonym to ' 'the current genus?\n\n<i>Note: This will not remove the ' 'genus from the database.</i>') % {'genus': s} if utils.yes_no_dialog(msg, parent=self.view.get_window()): tree_model.remove(tree_model.get_iter(path)) self.model.synonyms.remove(value.synonym) utils.delete_or_expunge(value) self.session.flush([value]) self._dirty = True self.refresh_sensitivity()
def on_file_menu_new(self, widget, data=None): msg = "If a database already exists at this connection then creating "\ "a new database could destroy your data.\n\n<i>Are you sure "\ "this is what you want to do?</i>" if not utils.yes_no_dialog(msg, yes_delay=2): return #if gui is not None and hasattr(gui, 'insert_menu'): submenu = self.insert_menu.get_submenu() for c in submenu.get_children(): submenu.remove(c) self.insert_menu.show() try: db.create() pluginmgr.init() except Exception, e: msg = _('Could not create a new database.\n\n%s') % \ utils.xml_safe(e) tb = utils.xml_safe(traceback.format_exc()) utils.message_details_dialog(msg, tb, gtk.MESSAGE_ERROR) return
def run(self, filename, objects=None): "perform the export" if filename is None: raise ValueError("filename can not be None") if os.path.exists(filename) and not os.path.isfile(filename): raise ValueError("%s exists and is not a a regular file" % filename) # if objects is None then export all objects under classes Familia, # Genus, Species, Accession, Plant, Location. if objects is None: s = db.Session() objects = s.query(Familia).all() objects.extend(s.query(Genus).all()) objects.extend(s.query(Species).all()) objects.extend(s.query(VernacularName).all()) objects.extend(s.query(Accession).all()) objects.extend(s.query(Plant).all()) objects.extend(s.query(Location).all()) count = len(objects) if count > 3000: msg = _('You are exporting %(nplants)s objects to JSON format. ' 'Exporting this many objects may take several minutes. ' '\n\n<i>Would you like to continue?</i>') \ % ({'nplants': count}) if not utils.yes_no_dialog(msg): return import codecs with codecs.open(filename, "wb", "utf-8") as output: output.write('[') output.write(',\n '.join( [json.dumps(obj.as_dict(), default=serializedatetime, sort_keys=True) for obj in objects])) output.write(']')
def _post_loop(): gtk.gdk.threads_enter() try: if isinstance(open_exc, err.DatabaseError): msg = _('Would you like to create a new Bauble database at ' 'the current connection?\n\n<i>Warning: If there is ' 'already a database at this connection any existing ' 'data will be destroyed!</i>') if utils.yes_no_dialog(msg, yes_delay=2): try: db.create() # db.create() creates all tables registered with # the default metadata so the pluginmgr should be # loaded after the database is created so we don't # inadvertantly create tables from the plugins pluginmgr.init() # set the default connection prefs[conn_default_pref] = conn_name except Exception, e: utils.message_details_dialog(utils.xml_safe(e), traceback.format_exc(), gtk.MESSAGE_ERROR) logger.error("%s(%s)" % (type(e), e)) else:
def _post_loop(): gtk.gdk.threads_enter() try: if isinstance(open_exc, err.DatabaseError): msg = _('Would you like to create a new Bauble database at ' \ 'the current connection?\n\n<i>Warning: If there is '\ 'already a database at this connection any existing '\ 'data will be destroyed!</i>') if utils.yes_no_dialog(msg, yes_delay=2): try: db.create() # db.create() creates all tables registered with # the default metadata so the pluginmgr should be # loaded after the database is created so we don't # inadvertantly create tables from the plugins pluginmgr.init() # set the default connection prefs[conn_default_pref] = conn_name except Exception, e: utils.message_details_dialog(utils.xml_safe_utf8(e), traceback.format_exc(), gtk.MESSAGE_ERROR) error(e) else:
except DBAPIError, e: msg = _('Error committing changes.\n\n%s') % \ utils.xml_safe(unicode(e.orig)) utils.message_details_dialog(msg, str(e), gtk.MESSAGE_ERROR) self.session.rollback() return False except Exception, e: msg = _('Unknown error when committing changes. See the ' 'details for more information.\n\n%s') %\ utils.xml_safe(e) logger.debug(traceback.format_exc()) utils.message_details_dialog(msg, traceback.format_exc(), gtk.MESSAGE_ERROR) self.session.rollback() return False elif self.presenter.dirty() and utils.yes_no_dialog(not_ok_msg) \ or not self.presenter.dirty(): self.session.rollback() return True else: return False return True def __del__(self): # override the editor.GenericModelViewPresenterEditor since it # will close the session but since we are called with the # AccessionEditor's session we don't want that # # TODO: when should we close the session and not, what about # is self.commit is True
try: # get all the dependencies for table, filename in sorted_tables: #debug(table.name) d = utils.find_dependent_tables(table) depends.update(list(d)) # drop all of the dependencies together if len(depends) > 0: if not force: msg = _('In order to import the files the following '\ 'tables will need to be dropped:' \ '\n\n<b>%s</b>\n\n' \ 'Would you like to continue?' \ % ', '.join(sorted([d.name for d in depends]))) response = utils.yes_no_dialog(msg) else: response = True if response and len(depends)>0: # debug('dropping: %s' \ # % ', '.join([d.name for d in depends])) metadata.drop_all(bind=connection, tables=depends) else: # user doesn't want to drop dependencies so we just quit return # commit the dependency drops transaction.commit() transaction = connection.begin()
except DBAPIError, e: msg = _('Error committing changes.\n\n%s') % \ utils.xml_safe(e.orig) utils.message_details_dialog(msg, str(e), gtk.MESSAGE_ERROR) self.session.rollback() return False except Exception, e: msg = _('Unknown error when committing changes. See the ' 'details for more information.\n\n%s') % \ utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), gtk.MESSAGE_ERROR) self.session.rollback() return False elif self.presenter.dirty() \ and utils.yes_no_dialog(not_ok_msg) \ or not self.presenter.dirty(): self.session.rollback() return True else: return False # respond to responses more_committed = None if response == self.RESPONSE_NEXT: self.presenter.cleanup() e = LocationEditor(parent=self.parent) more_committed = e.start() elif response == self.RESPONSE_OK_AND_ADD: from bauble.plugins.garden.plant import PlantEditor, Plant e = PlantEditor(Plant(location=self.model), self.parent)
self.update_infobox() statusbar = bauble.gui.widgets.statusbar sbcontext_id = statusbar.get_context_id('searchview.nresults') statusbar.pop(sbcontext_id) if len(results) == 0: model = gtk.ListStore(str) msg = bold % cgi.escape( _('Couldn\'t find anything for search: "%s"') % text) model.append([msg]) self.results_view.set_model(model) else: if len(results) > 5000: msg = _('This query returned %s results. It may take a ' 'long time to get all the data. Are you sure you ' 'want to continue?') % len(results) if not utils.yes_no_dialog(msg): return statusbar.push( sbcontext_id, _("Retrieving %s search " "results...") % len(results)) try: # don't bother with a task if the results are small, # this keeps the screen from flickering when the main # window is set to a busy state import time start = time.time() if len(results) > 1000: self.populate_results(results) else: task = self._populate_worker(results)
if self.presenter.dirty(): self.commit_changes() self._committed.append(self.model) except DBAPIError, e: msg = _('Error committing changes.\n\n%s') % \ utils.xml_safe_utf8(e.orig) utils.message_details_dialog(msg, str(e), gtk.MESSAGE_ERROR) return False except Exception, e: msg = _('Unknown error when committing changes. See the ' \ 'details for more information.\n\n%s') % \ utils.xml_safe_utf8(e) utils.message_details_dialog(msg, traceback.format_exc(), gtk.MESSAGE_ERROR) return False elif (self.presenter.dirty() and utils.yes_no_dialog(not_ok_msg)) or \ not self.presenter.dirty(): self.session.rollback() return True else: return False # respond to responses more_committed = None if response == self.RESPONSE_NEXT: self.presenter.cleanup() e = FamilyEditor(parent=self.parent) more_committed = e.start() elif response == self.RESPONSE_OK_AND_ADD: e = GenusEditor(Genus(family=self.model), self.parent) more_committed = e.start()
## get all the dependencies for table, filename in sorted_tables: logger.debug(table.name) d = utils.find_dependent_tables(table) depends.update(list(d)) del d ## drop all of the dependencies together if len(depends) > 0: if not force: msg = _('In order to import the files the following ' 'tables will need to be dropped:' '\n\n<b>%s</b>\n\n' 'Would you like to continue?' % ', '.join(sorted([d.name for d in depends]))) response = utils.yes_no_dialog(msg) else: response = True if response and len(depends) > 0: logger.debug('dropping: %s' % ', '.join([d.name for d in depends])) metadata.drop_all(bind=connection, tables=depends) else: # user doesn't want to drop dependencies so we just quit return # commit the dependency drops transaction.commit() transaction = connection.begin()
self._committed.append(self.model) except DBAPIError, e: msg = _('Error committing changes.\n\n%s') % \ utils.xml_safe(e.orig) logger.debug(traceback.format_exc()) utils.message_details_dialog(msg, str(e), gtk.MESSAGE_ERROR) return False except Exception, e: msg = _('Unknown error when committing changes. See the ' 'details for more information.\n\n%s') % \ utils.xml_safe(e) logger.debug(traceback.format_exc()) utils.message_details_dialog(msg, traceback.format_exc(), gtk.MESSAGE_ERROR) return False elif self.presenter.is_dirty() and utils.yes_no_dialog(not_ok_msg) \ or not self.presenter.is_dirty(): self.session.rollback() self.view.close_boxes() return True else: return False more_committed = None if response == self.RESPONSE_NEXT: self.presenter.cleanup() e = SpeciesEditorMenuItem( Species(genus=self.model.genus), self.parent) more_committed = e.start() elif response == self.RESPONSE_OK_AND_ADD: from bauble.plugins.garden.accession import (
except DBAPIError, e: msg = _('Error committing changes.\n\n%s') % \ utils.xml_safe(e.orig) utils.message_details_dialog(msg, str(e), gtk.MESSAGE_ERROR) self.session.rollback() return False except Exception, e: msg = _('Unknown error when committing changes. See the ' 'details for more information.\n\n%s') % \ utils.xml_safe(e) utils.message_details_dialog(msg, traceback.format_exc(), gtk.MESSAGE_ERROR) self.session.rollback() return False elif self.presenter.is_dirty() \ and utils.yes_no_dialog(not_ok_msg) \ or not self.presenter.is_dirty(): self.session.rollback() return True else: return False # respond to responses more_committed = None if response == self.RESPONSE_NEXT: self.presenter.cleanup() e = LocationEditor(parent=self.parent) more_committed = e.start() elif response == self.RESPONSE_OK_AND_ADD: from bauble.plugins.garden.plant import PlantEditor, Plant e = PlantEditor(Plant(location=self.model), self.parent)