def on_plant_code_entry_changed(self, entry, *args): """ Validates the accession number and the plant code from the editors. """ text = utils.utf8(entry.get_text()) if text == u'': self.set_model_attr('code', None) else: self.set_model_attr('code', utils.utf8(text)) if not self.model.accession: self.remove_problem(self.PROBLEM_DUPLICATE_PLANT_CODE, entry) self.refresh_sensitivity() return # add a problem if the code is not unique but not if its the # same accession and plant code that we started with when the # editor was opened if self.model.code is not None and not \ is_code_unique(self.model, self.model.code) and not \ (self._original_accession_id==self.model.accession.id and \ self.model.code==self._original_code): self.add_problem(self.PROBLEM_DUPLICATE_PLANT_CODE, entry) else: # remove_problem() won't complain if problem doesn't exist self.remove_problem(self.PROBLEM_DUPLICATE_PLANT_CODE, entry) entry.modify_bg(gtk.STATE_NORMAL, None) entry.modify_base(gtk.STATE_NORMAL, None) entry.queue_draw() self.refresh_sensitivity()
def run(self): """ """ response = self.window.run() self.window.hide() if response != gtk.RESPONSE_OK: return response stored_email = meta.get_default(PICASA_EMAIL_KEY).value.strip() email = self.widgets.email_entry.get_text().strip() album = self.widgets.album_entry.get_text().strip() passwd = self.widgets.password_entry.get_text().strip() if stored_email != email or self._changed: try: token = get_auth_token(email, passwd) except Exception, e: debug(e) token = None if not token: utils.message_dialog(_('Could not authorize Google '\ 'account: %s' % email), gtk.MESSAGE_ERROR) return False update_meta(utils.utf8(email), utils.utf8(album), utils.utf8(token))
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 add(self, id, path): """ Add photos to the cache """ session = self.Session() photo = Photo(id=utils.utf8(id), path=utils.utf8(path)) session.add(photo) session.commit() session.close()
def __init__(self, ): """ """ filename = os.path.join( paths.lib_dir(), 'plugins', 'users', 'ui.glade') super(UsersEditor, self).__init__(filename) if db.engine.name not in ('postgres', 'postgresql'): msg = _('The Users editor is only valid on a PostgreSQL database') utils.message_dialog(utils.utf8(msg)) return # TODO: should allow anyone to view the priveleges but only # admins to change them #debug(current_user()) if not has_privileges(current_user(), 'admin'): msg = _('You do not have privileges to change other '\ 'user privileges') utils.message_dialog(utils.utf8(msg)) return # setup the users tree tree = self.widgets.users_tree # remove any old columns for column in tree.get_columns(): tree.remove_column(column) renderer = gtk.CellRendererText() def cell_data_func(col, cell, model, it): value = model[it][0] cell.set_property('text', value) tree.insert_column_with_data_func(0, _('Users'), renderer, cell_data_func) self.connect(tree, 'cursor-changed', self.on_cursor_changed) self.connect(renderer, 'edited', self.on_cell_edited) # connect the filter_check and also adds the users to the users_tree self.connect('filter_check', 'toggled', self.on_filter_check_toggled) self.widgets.filter_check.set_active(True) def on_toggled(button, priv=None): buttons = (self.widgets.read_button, self.widgets.write_button, self.widgets.admin_button) role = self.get_selected_user() active = button.get_active() if active and not has_privileges(role, priv): #debug('grant %s to %s' % (priv, role)) try: set_privilege(role, priv) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window()) return True
def cell_data_func(self, col, cell, model, treeiter): path = model.get_path(treeiter) tree_rect = self.results_view.get_visible_rect() cell_rect = self.results_view.get_cell_area(path, col) if cell_rect.y > tree_rect.height: # only update the cells if they're visible...this # drastically speeds up populating the view with large # datasets return value = model[treeiter][0] if isinstance(value, basestring): cell.set_property('markup', value) else: # if the value isn't part of a session then add it to the # view's session so that we can access its child # properties...this usually happens when one of the # ViewMeta's get_children() functions return a list of # object who's session was closed...we add it here for # performance reasons so we only add it once it's visible if not object_session(value): if value in self.session: # expire the object in the session with the same key self.session.expire(value) else: self.session.add(value) try: func = self.view_meta[type(value)].markup_func if func is not None: r = func(value) if isinstance(r, (list, tuple)): main, substr = r else: main = r substr = '(%s)' % type(value).__name__ else: main = utils.xml_safe(str(value)) substr = '(%s)' % type(value).__name__ cell.set_property( 'markup', '%s\n%s' % (_mainstr_tmpl % utils.utf8(main), _substr_tmpl % utils.utf8(substr))) except (saexc.InvalidRequestError, TypeError), e: logger.warning( 'bauble.view.SearchView.cell_data_func(): \n%s' % e) def remove(): model = self.results_view.get_model() self.results_view.set_model(None) # detach model for found in utils.search_tree_model(model, value): model.remove(found) self.results_view.set_model(model) gobject.idle_add(remove)
def on_category_combo_changed(self, combo, *args): """ Sets the text on the entry. The model value is set in the entry "changed" handler. """ text = '' treeiter = combo.get_active_iter() if treeiter: text = utils.utf8(combo.get_model()[treeiter][0]) else: return self.widgets.category_comboentry.child.props.text = \ utils.utf8(text)
def add(plugin): """ Add a plugin to the registry. Warning: Adding a plugin to the registry does not install it. It should be installed before adding. """ p = PluginRegistry(name=utils.utf8(plugin.__class__.__name__), version=utils.utf8(plugin.version)) session = db.Session() session.add(p) session.commit() session.close()
def get_default(name, default=None, session=None): """ Get a BaubleMeta object with name. If the default value is not None then a BaubleMeta object is returned with name and the default value given. If a session instance is passed (session != None) then we don't commit the session. """ commit = False if not session: session = db.Session() commit = True query = session.query(BaubleMeta) meta = query.filter_by(name=name).first() if not meta and default is not None: meta = BaubleMeta(name=utils.utf8(name), value=default) session.add(meta) if commit: session.commit() # load the properties so that we can close the session and # avoid getting errors when accessing the properties on the # returned meta meta.value meta.name if commit: # close the session whether we added anything or not session.close() return meta
def on_response(button, response): self.view.remove_box(box) if response: self.view.widgets.sp_genus_entry.set_text(utils.utf8(syn.genus)) self.set_model_attr("genus", syn.genus) else: self.set_model_attr("genus", value)
def is_code_unique(plant, code): """ Return True/False if the code is a unique Plant code for accession. This method will also take range values for code that can be passed to utils.range_builder() """ # if the range builder only creates one number then we assume the # code is not a range and so we test against the string version of # code codes = map(utils.utf8, utils.range_builder(code)) # test if a range if len(codes) == 1: codes = [utils.utf8(code)] # reference accesssion.id instead of accession_id since # setting the accession on the model doesn't set the # accession_id until the session is flushed session = db.Session() count = ( session.query(Plant) .join("accession") .filter(and_(Accession.id == plant.accession.id, Plant.code.in_(codes))) .count() ) session.close() return count == 0
def on_category_entry_changed(self, entry, *args): """ """ value = utils.utf8(entry.props.text) if not value: # if value == '' value = None self.set_model_attr('category', value)
def on_lat_entry_changed(self, entry, date=None): """ set the latitude value from text """ from bauble.plugins.garden.accession import latitude_to_dms text = entry.get_text() latitude = None dms_string = "" try: if text != "" and text is not None: north_radio = self.view.widgets.north_radio north_radio.handler_block(self.north_toggle_signal_id) if text[0] == "-": self.view.widgets.south_radio.set_active(True) else: north_radio.set_active(True) north_radio.handler_unblock(self.north_toggle_signal_id) direction = self._get_lat_direction() latitude = CollectionPresenter._parse_lat_lon(direction, text) # u"\N{DEGREE SIGN}" dms_string = u"%s %s\u00B0%s'%s\"" % latitude_to_dms(latitude) except Exception: logger.debug(traceback.format_exc()) # bg_color = gtk.gdk.color_parse("red") self.add_problem(self.PROBLEM_BAD_LATITUDE, self.view.widgets.lat_entry) else: self.remove_problem(self.PROBLEM_BAD_LATITUDE, self.view.widgets.lat_entry) self.view.widgets.lat_dms_label.set_text(dms_string) if text is None or text.strip() == "": self.set_model_attr("latitude", None) else: self.set_model_attr("latitude", utils.utf8(latitude))
def on_lat_entry_changed(self, entry, date=None): ''' set the latitude value from text ''' from bauble.plugins.garden.accession import latitude_to_dms text = entry.get_text() latitude = None dms_string = '' try: if text != '' and text is not None: north_radio = self.view.widgets.north_radio north_radio.handler_block(self.north_toggle_signal_id) if text[0] == '-': self.view.widgets.south_radio.set_active(True) else: north_radio.set_active(True) north_radio.handler_unblock(self.north_toggle_signal_id) direction = self._get_lat_direction() latitude = CollectionPresenter._parse_lat_lon(direction, text) #u"\N{DEGREE SIGN}" dms_string = u'%s %s\u00B0%s\'%s"' % latitude_to_dms(latitude) except Exception: logger.debug(traceback.format_exc()) #bg_color = gtk.gdk.color_parse("red") self.add_problem(self.PROBLEM_BAD_LATITUDE, self.view.widgets.lat_entry) else: self.remove_problem(self.PROBLEM_BAD_LATITUDE, self.view.widgets.lat_entry) self.view.widgets.lat_dms_label.set_text(dms_string) if text is None or text.strip() == '': self.set_model_attr('latitude', None) else: self.set_model_attr('latitude', utils.utf8(latitude))
def on_pwd_button_clicked(self, button, *args): dialog = self.widgets.pwd_dialog dialog.set_transient_for(self.get_window()) def _on_something(d, *args): d.hide() return True self.connect(dialog, 'delete-event', _on_something) self.connect(dialog, 'close', _on_something) self.connect(dialog, 'response', _on_something) self.widgets.pwd_entry1.set_text('') self.widgets.pwd_entry2.set_text('') response = dialog.run() if response == gtk.RESPONSE_OK: pwd1 = self.widgets.pwd_entry1.get_text() pwd2 = self.widgets.pwd_entry2.get_text() user = self.get_selected_user() if pwd1 == '' or pwd2 == '': msg = _('The password for user <b>%s</b> has not been ' 'changed.') % user utils.message_dialog(msg, gtk.MESSAGE_WARNING, parent=self.get_window()) return elif pwd1 != pwd2: msg = _('The passwords do not match. The password for ' 'user <b>%s</b> has not been changed.') % user utils.message_dialog(msg, gtk.MESSAGE_WARNING, parent=self.get_window()) return else: try: set_password(pwd1, user) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
def on_lon_entry_changed(self, entry, data=None): from bauble.plugins.garden.accession import longitude_to_dms text = entry.get_text() longitude = None dms_string = '' try: if text != '' and text is not None: east_radio = self.view.widgets.east_radio east_radio.handler_block(self.east_toggle_signal_id) if text[0] == '-': self.view.widgets.west_radio.set_active(True) else: self.view.widgets.east_radio.set_active(True) east_radio.handler_unblock(self.east_toggle_signal_id) direction = self._get_lon_direction() longitude = CollectionPresenter._parse_lat_lon(direction, text) dms_string = u'%s %s\u00B0%s\'%s"' % longitude_to_dms( longitude) except Exception: logger.debug(traceback.format_exc()) #bg_color = gtk.gdk.color_parse("red") self.add_problem(self.PROBLEM_BAD_LONGITUDE, self.view.widgets.lon_entry) else: self.remove_problem(self.PROBLEM_BAD_LONGITUDE, self.view.widgets.lon_entry) self.view.widgets.lon_dms_label.set_text(dms_string) # self.set_model_attr('longitude', utils.utf8(longitude)) if text is None or text.strip() == '': self.set_model_attr('longitude', None) else: self.set_model_attr('longitude', utils.utf8(longitude))
def on_pwd_button_clicked(self, button, *args): dialog = self.widgets.pwd_dialog dialog.set_transient_for(self.get_window()) def _on_something(d, *args): d.hide() return True self.connect(dialog, "delete-event", _on_something) self.connect(dialog, "close", _on_something) self.connect(dialog, "response", _on_something) self.widgets.pwd_entry1.set_text("") self.widgets.pwd_entry2.set_text("") response = dialog.run() if response == gtk.RESPONSE_OK: pwd1 = self.widgets.pwd_entry1.get_text() pwd2 = self.widgets.pwd_entry2.get_text() user = self.get_selected_user() if pwd1 == "" or pwd2 == "": msg = _("The password for user <b>%s</b> has not been " "changed.") % user utils.message_dialog(msg, gtk.MESSAGE_WARNING, parent=self.get_window()) return elif pwd1 != pwd2: msg = _("The passwords do not match. The password for " "user <b>%s</b> has not been changed.") % user utils.message_dialog(msg, gtk.MESSAGE_WARNING, parent=self.get_window()) return else: try: set_password(pwd1, user) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
def _add(self, operation, mapper, instance): """ Add a new entry to the history table. """ user = None try: if engine.name.startswith('sqlite'): raise TypeError("this engine know nothing of users") import bauble.plugins.users as users user = users.current_user() except: if 'USER' in os.environ and os.environ['USER']: user = os.environ['USER'] elif 'USERNAME' in os.environ and os.environ['USERNAME']: user = os.environ['USERNAME'] row = {} for c in mapper.local_table.c: row[c.name] = utils.utf8(getattr(instance, c.name)) table = History.__table__ table.insert( dict(table_name=mapper.local_table.name, table_id=instance.id, values=str(row), operation=operation, user=user, timestamp=datetime.datetime.today())).execute()
def _add(self, operation, mapper, instance): """ Add a new entry to the history table. """ user = None from bauble import db try: if db.engine.name in ('postgres', 'postgresql'): import bauble.plugins.users as users user = users.current_user() except: if 'USER' in os.environ and os.environ['USER']: user = os.environ['USER'] elif 'USERNAME' in os.environ and os.environ['USERNAME']: user = os.environ['USERNAME'] row = {} for c in mapper.local_table.c: row[c.name] = utils.utf8(getattr(instance, c.name)) table = History.__table__ table.insert( dict(table_name=mapper.local_table.name, table_id=instance.id, values=str(row), operation=operation, user=user, timestamp=datetime.datetime.today())).execute()
def on_lon_entry_changed(self, entry, data=None): from bauble.plugins.garden.accession import longitude_to_dms text = entry.get_text() longitude = None dms_string = "" try: if text != "" and text is not None: east_radio = self.view.widgets.east_radio east_radio.handler_block(self.east_toggle_signal_id) if text[0] == "-": self.view.widgets.west_radio.set_active(True) else: self.view.widgets.east_radio.set_active(True) east_radio.handler_unblock(self.east_toggle_signal_id) direction = self._get_lon_direction() longitude = CollectionPresenter._parse_lat_lon(direction, text) dms_string = u"%s %s\u00B0%s'%s\"" % longitude_to_dms(longitude) except Exception: logger.debug(traceback.format_exc()) # bg_color = gtk.gdk.color_parse("red") self.add_problem(self.PROBLEM_BAD_LONGITUDE, self.view.widgets.lon_entry) else: self.remove_problem(self.PROBLEM_BAD_LONGITUDE, self.view.widgets.lon_entry) self.view.widgets.lon_dms_label.set_text(dms_string) # self.set_model_attr('longitude', utils.utf8(longitude)) if text is None or text.strip() == "": self.set_model_attr("longitude", None) else: self.set_model_attr("longitude", utils.utf8(longitude))
def get_tagged_objects(tag, session=None): """ Return all object tagged with tag. :param tag: A string or :class:`Tag` :param session: """ close_session = False if not isinstance(tag, Tag): if not session: session = db.Session() tag = session.query(Tag).filter_by(tag=utils.utf8(tag)).first() elif not session: from sqlalchemy.orm.session import object_session session = object_session(tag) # filter out any None values from the query which can happen if # you tag something and then delete it from the datebase # TODO: the missing tagged objects should probably be removed from # the database r = [session.query(mapper).filter_by(id=obj_id).first() for mapper, obj_id in _get_tagged_object_pairs(tag)] r = filter(lambda x: x is not None, r) if close_session: session.close() return r
def _add(self, operation, mapper, instance): """ Add a new entry to the history table. """ user = None from bauble import db try: if db.engine.name in ("postgres", "postgresql"): import bauble.plugins.users as users user = users.current_user() except: if "USER" in os.environ and os.environ["USER"]: user = os.environ["USER"] elif "USERNAME" in os.environ and os.environ["USERNAME"]: user = os.environ["USERNAME"] row = {} for c in mapper.local_table.c: row[c.name] = utils.utf8(getattr(instance, c.name)) table = History.__table__ table.insert( dict( table_name=mapper.local_table.name, table_id=instance.id, values=str(row), operation=operation, user=user, timestamp=datetime.datetime.today(), ) ).execute()
def update(self, row): """ Update the Picasa info page. :param: a Species instance """ self._current_row = row token_meta = meta.get_default(utils.utf8(PICASA_TOKEN_KEY)) if not token_meta: msg = _('Could not login to PicasaWeb account.') self.on_error(msg, species=row) return token = token_meta.value self.gd_client.SetClientLoginToken(token) tag = Species.str(row, markup=False, authors=False) self.set_busy() worker = populate_iconview(self.gd_client, self.iconview, tag) def on_done(*args): if not _exc_queue.empty(): exc = _exc_queue.get() msg = 'Could not retrieve the photos.\n\n' if isinstance(exc, gdata.photos.service.GooglePhotosException): msg += exc.message else: msg += str(exc) gobject.idle_add(self.on_error, msg, row) return self.set_busy(False) model = self.iconview.get_model() if len(model) == 0: gobject.idle_add(self.status_box.set_text, _('No images')) gobject.idle_add(self.show_status_box) else: gobject.idle_add(self.hide_status_box) worker.connect('done', on_done, False)
def on_rooted_cell_edited(self, cell, path, new_text, prop): treemodel = self.view.widgets.rooted_treeview.get_model() rooted = treemodel[path][0] if getattr(rooted, prop) == new_text: return # didn't change setattr(rooted, prop, utils.utf8(new_text)) self._dirty = True self.parent_ref().refresh_sensitivity()
def on_cell_edited(self, cell, path, new_text, prop): treemodel = self.treeview.get_model() vn = treemodel[path][0] if getattr(vn, prop) == new_text: return # didn't change setattr(vn, prop, utils.utf8(new_text)) self._dirty = True self.parent_ref().refresh_sensitivity()
def on_rank_combo_changed(self, combo, *args): model = combo.get_model() it = combo.get_active_iter() value = model[it][0] if value is not None: self.set_model_attr('rank', utils.utf8(model[it][0])) else: self.set_model_attr('rank', None)
def on_response(button, response): self.view.remove_box(box) if response: self.view.widgets.sp_genus_entry.\ set_text(utils.utf8(syn.genus)) self.set_model_attr('genus', syn.genus) else: self.set_model_attr('genus', value)
def test_bulk_plant_editor(self): """ Test creating multiple plants with the plant editor. """ try: import gtk except ImportError: raise SkipTest('could not import gtk') # use our own plant because PlantEditor.commit_changes() will # only work in bulk mode when the plant is in session.new p = Plant(accession=self.accession, location=self.location, code=u'2', quantity=52) self.editor = PlantEditor(model=p) #editor.start() update_gui() rng = '2,3,4-6' for code in utils.range_builder(rng): q = self.session.query(Plant).join('accession').\ filter(and_(Accession.id==self.plant.accession.id, Plant.code==utils.utf8(code))) self.assert_(not q.first(), 'code already exists') widgets = self.editor.presenter.view.widgets # make sure the entry gets a Problem added to it if an # existing plant code is used in bulk mode widgets.plant_code_entry.set_text('1,' + rng) widgets.plant_quantity_entry.set_text('2') update_gui() problem = (self.editor.presenter.PROBLEM_DUPLICATE_PLANT_CODE, self.editor.presenter.view.widgets.plant_code_entry) self.assert_(problem in self.editor.presenter.problems, 'no problem added for duplicate plant code') # create multiple plant codes widgets.plant_code_entry.set_text(rng) update_gui() self.editor.handle_response(gtk.RESPONSE_OK) for code in utils.range_builder(rng): q = self.session.query(Plant).join('accession').\ filter(and_(Accession.id==self.plant.accession.id, Plant.code==utils.utf8(code))) self.assert_(q.first(), 'plant %s.%s not created' % \ (self.accession, code))
def update_meta(email=None, album=None, token=None): """ Update the email, album and authorization token in the bauble meta table. """ # TODO: should we allow setting the values to None session = db.Session() if email: email = utils.utf8(email) meta.get_default(PICASA_EMAIL_KEY, email, session).value = email if album: album = utils.utf8(album) meta.get_default(PICASA_ALBUM_KEY, album, session).value = album if token: token = utils.utf8(token) meta.get_default(PICASA_TOKEN_KEY, token, session).value = token session.commit() session.close() __feed_cache.clear()
def on_response(button, response): self.view.widgets.remove_parent(box) box.destroy() if response: self.view.widgets.sp_genus_entry.\ set_text(utils.utf8(syn.genus)) self.set_model_attr('genus', syn.genus) else: self.set_model_attr('genus', value)
def __getitem__(self, id): """ Get photos from the database by tag """ # select item from database and return a list of matching filenames session = self.Session() photo = session.query(Photo).filter_by(id=utils.utf8(id)).first() session.close() return photo
def on_rank_combo_changed(self, combo, *args): logger.info("on_rank_combo_changed(%s, %s)" % (combo, args)) model = combo.get_model() it = combo.get_active_iter() value = model[it][0] if value is not None: self.set_model_attr('rank', utils.utf8(model[it][0])) else: self.set_model_attr('rank', None)
def create(import_defaults=True): """ Create new Bauble database at the current connection :param import_defaults: A flag that is passed to each plugins install() method to indicate where it should import its default data. This is mainly used for testing. The default value is True :type import_defaults: bool """ # TODO: when creating a database there shouldn't be any errors # on import since we are importing from the default values, we should # just force the import and send everything in the database at once # instead of using slices, this would make it alot faster but it may # make it more difficult to make the interface more responsive, # maybe we can use a dialog without the progress bar to show the status, # should probably work on the status bar to display this # TODO: we create a transaction here and the csv import creates another # nested transaction, we need to verify that if we rollback here then all # of the changes made by csv import are rolled back as well ## debug('entered db.create()') if not engine: raise ValueError('engine is None, not connected to a database') import bauble import bauble.meta as meta import bauble.pluginmgr as pluginmgr import datetime connection = engine.connect() transaction = connection.begin() try: # TODO: here we are dropping/creating all the tables in the # metadata whether they are in the registry or not, we should # really only be creating those tables from registered # plugins, maybe with an uninstall() method on Plugin metadata.drop_all(bind=connection, checkfirst=True) metadata.create_all(bind=connection) # fill in the bauble meta table and install all the plugins meta_table = meta.BaubleMeta.__table__ meta_table.insert(bind=connection).\ execute(name=meta.VERSION_KEY, value=unicode(bauble.version)).close() meta_table.insert(bind=connection).\ execute(name=meta.CREATED_KEY, value=unicode(datetime.datetime.now())).close() except GeneratorExit, e: # this is here in case the main windows is closed in the middle # of a task # UPDATE 2009.06.18: i'm not sure if this is still relevant since we # switched the task system to use fibra...but it doesn't hurt # having it here until we can make sure warning('bauble.db.create(): %s' % utils.utf8(e)) transaction.rollback() raise
def on_rank_combo_changed(self, combo, *args): logger.info("on_rank_combo_changed(%s, %s)" % (combo, args)) model = combo.get_model() it = combo.get_active_iter() value = model[it][0] if value is not None: self.set_model_attr("rank", utils.utf8(model[it][0])) else: self.set_model_attr("rank", None)
def remove(self, id): """ Remove a photo entry from the cache. """ session = self.Session() photo = self[utils.utf8(id)] session.delete(photo) session.commit() session.close()
def on_entry_changed(entry, presenter): logger.debug('on_entry_changed(%s, %s)', entry, presenter) text = utils.utf8(entry.props.text) if not text and not required: presenter.remove_problem(PROBLEM, entry) on_select(None) return # see if the text matches a completion string comp = entry.get_completion() compl_model = comp.get_model() def _cmp(row, data): return utils.utf8(row[0]) == data found = utils.search_tree_model(compl_model, text, _cmp) if len(found) == 1: comp.emit('match-selected', compl_model, found[0]) return True # if text looks like '(code) name', then split it into the two # parts, then see if the text matches exactly a code or name match = re_code_name_splitter.match(text) if match: code, name = match.groups() else: code = name = text codes = presenter.session.query(Location).\ filter(utils.ilike(Location.code, '%s' % utils.utf8(code))) names = presenter.session.query(Location).\ filter(utils.ilike(Location.name, '%s' % utils.utf8(name))) if codes.count() == 1: logger.debug('location matches code') location = codes.first() presenter.remove_problem(PROBLEM, entry) on_select(location) elif names.count() == 1: logger.debug('location matches name') location = names.first() presenter.remove_problem(PROBLEM, entry) on_select(location) else: logger.debug('location %s does not match anything' % text) presenter.add_problem(PROBLEM, entry) return True
def quit(): """ Stop all tasks and quit Bauble. """ import gtk import bauble.utils as utils try: import bauble.task as task except Exception, e: logger.error('bauble.quit(): %s' % utils.utf8(e))
def on_toggled(button, priv=None): buttons = (self.widgets.read_button, self.widgets.write_button, self.widgets.admin_button) role = self.get_selected_user() active = button.get_active() if active and not has_privileges(role, priv): # debug('grant %s to %s' % (priv, role)) try: set_privilege(role, priv) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
def cell_data_func(col, cell, model, treeiter, prop): row = model[treeiter][0] val = getattr(row, prop) if val: if prop == 'date': format = prefs.prefs[prefs.date_format_pref] val = val.strftime(format) cell.set_property('text', utils.utf8(val)) else: cell.set_property('text', '')
def get_Notes(self): if not self.species.notes: return None notes = [] for note in self.species.notes: notes.append( dict(date=utils.xml_safe(note.date.isoformat()), user=utils.xml_safe(note.user), category=utils.xml_safe(note.category), note=utils.xml_safe(note.note))) return utils.utf8(notes)
def write(self): for prop in self.__properties: value = getattr(self, prop) prop = utils.utf8(prop) value = utils.utf8(value) result = self.table.select(self.table.c.name == prop).\ execute() row = result.fetchone() result.close() # have to check if the property exists first because sqlite doesn't # raise an error if you try to update a value that doesn't exist # and do an insert and then catching the exception if it exists # and then updating the value is too slow if not row: #debug('insert: %s = %s' % (prop, value)) self.table.insert().execute(name=prop, value=value) else: #debug('update: %s = %s' % (prop, value)) self.table.update( self.table.c.name == prop).execute(value=value)
def __init__(self): # initialize properties to None map(lambda p: setattr(self, p, None), self.__properties) for prop in self.__properties: prop = utils.utf8(prop) result = self.table.select(self.table.c.name == prop).execute() row = result.fetchone() if row: setattr(self, prop, row['value']) result.close()
def on_toggled(button, priv=None): buttons = (self.widgets.read_button, self.widgets.write_button, self.widgets.admin_button) role = self.get_selected_user() active = button.get_active() if active and not has_privileges(role, priv): #debug('grant %s to %s' % (priv, role)) try: set_privilege(role, priv) except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
def remove(plugin=None, name=None): """ Remove a plugin from the registry by name. """ #debug('PluginRegistry.remove()') if name is None: name = plugin.__class__.__name__ session = db.Session() p = session.query(PluginRegistry).\ filter_by(name=utils.utf8(name)).one() session.delete(p) session.commit() session.close()
def install(plugins_to_install, import_defaults=True, force=False): """ :param plugins_to_install: A list of plugins to install. If the string "all" is passed then install all plugins listed in the bauble.pluginmgr.plugins dict that aren't already listed in the plugin registry. :param import_defaults: Flag passed to the plugin's install() method to indicate whether it should import its default data. :type import_defaults: bool :param force: Force, don't ask questions. :type force: book """ logger.debug('pluginmgr.install(%s)' % str(plugins_to_install)) if plugins_to_install is 'all': to_install = plugins.values() else: to_install = plugins_to_install if len(to_install) == 0: # no plugins to install return # sort the plugins by their dependency depends, unmet = _create_dependency_pairs(to_install) if unmet != {}: logger.debug(unmet) raise BaubleError('unmet dependencies') to_install = utils.topological_sort(to_install, depends) if not to_install: raise BaubleError( _('The plugins contain a dependency loop. This ' 'can happend if two plugins directly or ' 'indirectly rely on each other')) try: for p in to_install: logger.debug('install: %s' % p) p.install(import_defaults=import_defaults) # issue #28: here we make sure we don't add the plugin to the # registry twice but we should really update the version number # in the future when we accept versioned plugins (if ever) if not PluginRegistry.exists(p): PluginRegistry.add(p) except Exception, e: logger.warning('bauble.pluginmgr.install(): %s' % utils.utf8(e)) raise
class ReportTool(pluginmgr.Tool): label = _("Report") @classmethod def start(self): ''' ''' # get the select results from the search view from bauble.view import SearchView view = bauble.gui.get_view() if not isinstance(view, SearchView): utils.message_dialog(_('Search for something first.')) return model = view.results_view.get_model() if model is None: utils.message_dialog(_('Search for something first.')) return bauble.gui.set_busy(True) ok = False try: while True: dialog = ReportToolDialog() formatter, settings = dialog.start() if formatter is None: break ok = formatter.format([row[0] for row in model], **settings) if ok: break except AssertionError, e: logger.debug(e) logger.debug(traceback.format_exc()) parent = None if hasattr(self, 'view') and hasattr(self.view, 'dialog'): parent = self.view.dialog utils.message_details_dialog(str(e), traceback.format_exc(), gtk.MESSAGE_ERROR, parent=parent) except Exception, e: logger.debug(traceback.format_exc()) utils.message_details_dialog( _('Formatting Error\n\n' '%(exception)s') % {"exception": utils.utf8(e)}, traceback.format_exc(), gtk.MESSAGE_ERROR)
def on_cell_edited(self, cell, path, new_text, data=None): model = self.widgets.users_tree.get_model() user = new_text if user == self.new_user_message: # didn't change so don't add the user treeiter = model.get_iter((len(model)-1,)) model.remove(treeiter) return True model[path] = (user,) try: create_user(user) set_privilege(user, 'read') except Exception, e: utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window()) model.remove(model.get_iter(path))
def on_habit_comboentry_changed(self, combo, *args): """ Changed handler for sp_habit_comboentry. We don't need specific handlers for either comboentry because the validation is done in the specific gtk.Entry handlers for the child of the combo entries. """ treeiter = combo.get_active_iter() if not treeiter: return value = combo.get_model()[treeiter][1] self.set_model_attr('habit', value) # the entry change handler does the validation of the model combo.child.props.text = utils.utf8(value) combo.child.set_position(-1)
def set_password(password, user=None): """ Set a user's password. If user is None then change the password of the current user. """ if not user: user = current_user() conn = db.engine.connect() trans = conn.begin() try: stmt = "alter role %s with encrypted password '%s'" % (user, password) conn.execute(stmt) except Exception, e: error('users.set_password(): %s' % utils.utf8(e)) trans.rollback()
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())