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))
Esempio n. 3
0
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()
Esempio n. 5
0
    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
Esempio n. 6
0
    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)
Esempio n. 7
0
    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)
Esempio n. 8
0
    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 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()
Esempio n. 11
0
    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()
Esempio n. 12
0
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)
Esempio n. 14
0
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
Esempio n. 15
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)
Esempio n. 16
0
    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))
Esempio n. 17
0
    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))
Esempio n. 18
0
 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())
Esempio n. 19
0
    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))
Esempio n. 20
0
    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())
Esempio n. 21
0
    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()
Esempio n. 22
0
    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()
Esempio n. 23
0
    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
Esempio n. 25
0
    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)
Esempio n. 27
0
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
Esempio n. 28
0
 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()
Esempio n. 29
0
 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)
Esempio n. 31
0
 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)
Esempio n. 32
0
    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)
Esempio n. 35
0
 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
Esempio n. 36
0
 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)
Esempio n. 37
0
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
Esempio n. 38
0
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 __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 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()
Esempio n. 42
0
 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()
Esempio n. 43
0
    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
Esempio n. 44
0
    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
Esempio n. 45
0
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))
Esempio n. 46
0
 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())
Esempio n. 47
0
 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', '')
Esempio n. 48
0
 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', '')
Esempio n. 49
0
 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)
Esempio n. 50
0
 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)
Esempio n. 51
0
    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()
Esempio n. 52
0
 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())
Esempio n. 53
0
 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()
Esempio n. 54
0
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
Esempio n. 55
0
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)
Esempio n. 56
0
 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))
Esempio n. 57
0
    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)
Esempio n. 58
0
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()
Esempio n. 59
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 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())