Exemplo n.º 1
0
def _on_add_tag_activated(*args):
    # get the selection from the search view
    # TODO: would be better if we could set the sensitivity of the menu
    # item depending on if something was selected in the search view, this
    # means we need to add more hooks to the search view or include the
    # tag plugin into the search view
    view = bauble.gui.get_view()
    if isinstance(view, SearchView):
        values = view.get_selected_values()
        if len(values) == 0:
            msg = _('Nothing selected')
            utils.message_dialog(msg)
            return
        # right now we can only tag a single item at a time, if we did
        # the f-spot style quick tagging then it would be easier to handle
        # multiple tags at a time, we could do it we would just have to find
        # the common tags for each of the selected items and then select them
        # but grey them out so you can see that some of the items have that
        # tag but not all of them
        tagitem = TagItemGUI(values)
        tagitem.start()
        view.update_bottom_notebook()
    else:
        msg = _('In order to tag an item you must first search for '
                'something and select one of the results.')
        bauble.gui.show_message_box(msg)
    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:
            debug(e)
            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)
Exemplo n.º 3
0
    def run(self, filename, plants=None):
        if filename == None:
            raise ValueError("filename can not be None")

        if os.path.exists(filename) and not os.path.isfile(filename):
            raise ValueError("%s exists and is not a a regular file" \
                                 % filename)

        # if plants is None then export all plants, this could be huge
        # TODO: do something about this, like list the number of plants
        # to be returned and make sure this is what the user wants
        if plants == None:
            plants = db.Session().query(Plant).all()

        # TODO: move PlantABCDAdapter, AccessionABCDAdapter and
        # PlantABCDAdapter into the ABCD plugin
        from bauble.plugins.report.xsl import PlantABCDAdapter
        data = create_abcd([PlantABCDAdapter(p) for p in plants],
                           validate=False)

        data.write_c14n(filename)

        # validate after the file is written so we still have some
        # output but let the user know the file isn't valid ABCD
        if not validate_xml(data):
            msg = _("The ABCD file was created but failed to validate "
                    "correctly against the ABCD standard.")
            utils.message_dialog(msg, gtk.MESSAGE_WARNING)
    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))
Exemplo n.º 5
0
 def format(objs, **kwargs):
     template_filename = kwargs['template']
     use_private = kwargs.get('private', True)
     if not template_filename:
         msg = _('Please select a template.')
         utils.message_dialog(msg, gtk.MESSAGE_WARNING)
         return False
     template = Template(filename=template_filename,
                         input_encoding='utf-8',
                         output_encoding='utf-8')
     session = db.Session()
     values = map(session.merge, objs)
     report = template.render(values=values)
     session.close()
     # assume the template is the same file type as the output file
     head, ext = os.path.splitext(template_filename)
     fd, filename = tempfile.mkstemp(suffix=ext)
     os.write(fd, report)
     os.close(fd)
     try:
         desktop.open(filename)
     except OSError:
         utils.message_dialog(
             _('Could not open the report with the '
               'default program. You can open the '
               'file manually at %s') % filename)
     return report
Exemplo n.º 6
0
    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:
                logger.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))
Exemplo n.º 7
0
def _on_add_tag_activated(*args):
    # get the selection from the search view
    # TODO: would be better if we could set the sensitivity of the menu
    # item depending on if something was selected in the search view, this
    # means we need to add more hooks to the search view or include the
    # tag plugin into the search view
    view = bauble.gui.get_view()
    if isinstance(view, SearchView):
        values = view.get_selected_values()
        if len(values) == 0:
            msg = _('Nothing selected')
            utils.message_dialog(msg)
            return
        # right now we can only tag a single item at a time, if we did
        # the f-spot style quick tagging then it would be easier to handle
        # multiple tags at a time, we could do it we would just have to find
        # the common tags for each of the selected items and then select them
        # but grey them out so you can see that some of the items have that
        # tag but not all of them
        tagitem = TagItemGUI(values)
        tagitem.start()
        view.update_bottom_notebook()
    else:
        msg = _('In order to tag an item you must first search for '
                'something and select one of the results.')
        bauble.gui.show_message_box(msg)
Exemplo n.º 8
0
 def format(objs, **kwargs):
     template_filename = kwargs["template"]
     use_private = kwargs.get("private", True)
     if not template_filename:
         msg = _("Please select a template.")
         utils.message_dialog(msg, gtk.MESSAGE_WARNING)
         return False
     template = Template(filename=template_filename, input_encoding="utf-8", output_encoding="utf-8")
     session = db.Session()
     values = map(session.merge, objs)
     report = template.render(values=values)
     session.close()
     # assume the template is the same file type as the output file
     head, ext = os.path.splitext(template_filename)
     fd, filename = tempfile.mkstemp(suffix=ext)
     os.write(fd, report)
     os.close(fd)
     try:
         desktop.open(filename)
     except OSError:
         utils.message_dialog(
             _("Could not open the report with the " "default program. You can open the " "file manually at %s")
             % filename
         )
     return report
Exemplo n.º 9
0
    def run(self, filenames, metadata, force=False):
        '''
        A generator method for importing filenames into the database.
        This method periodically yields control so that the GUI can
        update.

        :param filenames:
        :param metadata:
        :param force: default=False
        '''
        transaction = None
        connection = None
        self.__error_exc = BaubleError(_('Unknown Error.'))

        try:
            # user a contextual connect in case whoever called this
            # method called it inside a transaction then we can pick
            # up the parent connection and the transaction
            connection = metadata.bind.connect()
            transaction = connection.begin()
        except Exception, e:
            msg = _('Error connecting to database.\n\n%s') % \
                  utils.xml_safe_utf8(e)
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            return
Exemplo n.º 10
0
    def run(self, filenames, metadata, force=False):
        '''
        A generator method for importing filenames into the database.
        This method periodically yields control so that the GUI can
        update.

        :param filenames:
        :param metadata:
        :param force: default=False
        '''
        transaction = None
        connection = None
        self.__error_exc = BaubleError(_('Unknown Error.'))

        try:
            # user a contextual connect in case whoever called this
            # method called it inside a transaction then we can pick
            # up the parent connection and the transaction
            connection = metadata.bind.connect()
            transaction = connection.begin()
        except Exception, e:
            msg = _('Error connecting to database.\n\n%s') % \
                utils.xml_safe(e)
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            return
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    def run(self, filename, plants=None):
        if filename == None:
            raise ValueError("filename can not be None")

        if os.path.exists(filename) and not os.path.isfile(filename):
            raise ValueError("%s exists and is not a a regular file" \
                                 % filename)

        # if plants is None then export all plants, this could be huge
        # TODO: do something about this, like list the number of plants
        # to be returned and make sure this is what the user wants
        if plants == None:
            plants = db.Session().query(Plant).all()

        # TODO: move PlantABCDAdapter, AccessionABCDAdapter and
        # PlantABCDAdapter into the ABCD plugin
        from bauble.plugins.report.xsl import PlantABCDAdapter
        data = create_abcd([PlantABCDAdapter(p) for p in plants],
                           validate=False)

        data.write_c14n(filename)

        # validate after the file is written so we still have some
        # output but let the user know the file isn't valid ABCD
        if not validate_xml(data):
            msg = _("The ABCD file was created but failed to validate "
                    "correctly against the ABCD standard.")
            utils.message_dialog(msg, gtk.MESSAGE_WARNING)
Exemplo n.º 13
0
    def start(self):
        """
        Show the connection manager.
        """
        self.create_gui()
        conn_list = prefs.prefs[bauble.conn_list_pref]
        if conn_list is None or len(conn_list.keys()) == 0:
            msg = _('You don\'t have any connections in your connection '
                    'list.\nClose this message and click on "Add" to create '
                    'a new connection.')
            utils.message_dialog(msg)
        else:
            self.set_active_connection_by_name(self.default_name)
            self._dirty = False

        self._error = True
        name = None
        uri = None
        while name is None or self._error:
            response = self.dialog.run()
            if response == gtk.RESPONSE_OK:
                name = self._get_connection_name()
                uri = self._get_connection_uri()
                if name is None:
                    msg = _('You have to choose or create a new connection '
                            'before you can connect to the database.')
                    utils.message_dialog(msg)
            else:
                name = uri = None
                break

        ## now make sure the pictures dir contains a thumbs subdir
        path = os.path.sep.join(
            (prefs.prefs[prefs.picture_root_pref], 'thumbs'))
        try:
            logger.debug("checking presence of thumbs dir")
            os.makedirs(path)
        except OSError:
            if not os.path.isdir(path):
                logger.debug("something wrong in thumbs dir")
                raise

        # have to remove the cell_data_func to avoid a cyclical
        # reference which would cause the ConnectionManager to not get
        # garbage collected
        cell = self.type_combo.get_cells()[0]
        self.type_combo.set_cell_data_func(cell, None)
        self.type_combo.clear()
        self.name_combo.clear()

        # just to be sure let's destroy the dialog upfront and delete
        # the params box
        self.dialog.destroy()
        del self.params_box
        obj = utils.gc_objects_by_type(CMParamsBox)
        if obj:
            logger.info('ConnectionManager.start(): param box leaked: %s' %
                        obj)
        return name, uri
Exemplo n.º 14
0
    def start(self):
        """
        Show the connection manager.
        """
        self.create_gui()
        conn_list = prefs.prefs[bauble.conn_list_pref]
        if conn_list is None or len(conn_list.keys()) == 0:
            msg = _('You don\'t have any connections in your connection '
                    'list.\nClose this message and click on "Add" to create '
                    'a new connection.')
            utils.message_dialog(msg)
        else:
            self.set_active_connection_by_name(self.default_name)
            self._dirty = False

        self._error = True
        name = None
        uri = None
        while name is None or self._error:
            response = self.dialog.run()
            if response == gtk.RESPONSE_OK:
                name = self._get_connection_name()
                uri = self._get_connection_uri()
                if name is None:
                    msg = _('You have to choose or create a new connection '
                            'before you can connect to the database.')
                    utils.message_dialog(msg)
            else:
                name = uri = None
                break

        ## now make sure the pictures dir contains a thumbs subdir
        path = os.path.sep.join(
            (prefs.prefs[prefs.picture_root_pref], 'thumbs'))
        try:
            logger.debug("checking presence of thumbs dir")
            os.makedirs(path)
        except OSError:
            if not os.path.isdir(path):
                logger.debug("something wrong in thumbs dir")
                raise

        # have to remove the cell_data_func to avoid a cyclical
        # reference which would cause the ConnectionManager to not get
        # garbage collected
        cell = self.type_combo.get_cells()[0]
        self.type_combo.set_cell_data_func(cell, None)
        self.type_combo.clear()
        self.name_combo.clear()

        # just to be sure let's destroy the dialog upfront and delete
        # the params box
        self.dialog.destroy()
        del self.params_box
        obj = utils.gc_objects_by_type(CMParamsBox)
        if obj:
            logger.info('ConnectionManager.start(): param box leaked: %s'
                        % obj)
        return name, uri
Exemplo n.º 15
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 should be called after after Bauble has established a
    connection to a database with db.open()
    """

    logger.debug('bauble.pluginmgr.init()')
    # ******
    # NOTE: Be careful not to keep any references to
    # PluginRegistry open here as it will cause a deadlock if you try
    # to create a new database. For example, don't query the
    # PluginRegistry with a session without closing the session.
    # ******

    # search for plugins that are in the plugins dict but not in the registry
    registered = plugins.values()
    logger.debug('registered plugins: %s' % plugins)
    try:
        # try to access the plugin registry, if the table does not exist
        # then it might mean that we are opening a pre 0.9 database, in this
        # case we just assume all the plugins have been installed and
        # registered, this might be the right thing to do but at least it
        # allows you to connect to a pre bauble 0.9 database and use it to
        # upgrade to a >=0.9 database
        registered_names = PluginRegistry.names()
        not_installed = [
            p for n, p in plugins.iteritems() if n not in registered_names
        ]
        if len(not_installed) > 0:
            msg = _('The following plugins were not found in the plugin '
                    'registry:\n\n<b>%s</b>\n\n'
                    '<i>Would you like to install them now?</i>' %
                    ', '.join([p.__class__.__name__ for p in not_installed]))
            if force or utils.yes_no_dialog(msg):
                install([p for p in not_installed])

        # sort plugins in the registry by their dependencies
        not_registered = []
        for name in PluginRegistry.names():
            try:
                registered.append(plugins[name])
            except KeyError, e:
                logger.debug("could not find '%s' plugin. "
                             "removing from database" % e)
                not_registered.append(utils.utf8(name))
                PluginRegistry.remove(name=name)

        if not_registered:
            msg = _('The following plugins are in the registry but '
                    'could not be loaded:\n\n%(plugins)s' %
                    {'plugins': utils.utf8(', '.join(sorted(not_registered)))})
            utils.message_dialog(utils.xml_safe(msg), type=gtk.MESSAGE_WARNING)
Exemplo n.º 16
0
 def init_names_combo(self):
     formatters = prefs[config_list_pref]
     if formatters is None or len(formatters) == 0:
         msg = _('No formatters found. To create a new formatter click '\
                 'the "New" button.')
         utils.message_dialog(msg, parent=self.view.dialog)
         self.view.widgets.names_combo.set_model(None)
     self.populate_names_combo()
Exemplo n.º 17
0
 def init_names_combo(self):
     formatters = prefs[config_list_pref]
     if formatters is None or len(formatters) == 0:
         msg = _('No formatters found. To create a new formatter click '
                 'the "New" button.')
         utils.message_dialog(msg, parent=self.view.dialog)
         self.view.widgets.names_combo.set_model(None)
     self.populate_names_combo()
Exemplo n.º 18
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)
Exemplo n.º 19
0
def branch_callback(plants):
    if plants[0].quantity <= 1:
        msg = _("Not enough plants to branch.  A plant should have at least "
                "a quantity of 2 before it can be branched")
        utils.message_dialog(msg, gtk.MESSAGE_WARNING)
        return

    e = PlantEditor(model=plants[0], branch_mode=True)
    return e.start() != None
Exemplo n.º 20
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
Exemplo n.º 21
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())
Exemplo n.º 22
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())
Exemplo n.º 23
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
Exemplo n.º 24
0
 def save(self):
     try:
         f = open(self._filename, "w+")
         self.config.write(f)
         f.close()
     except Exception:
         msg = _("Bauble can't save your user preferences. \n\nPlease "
                 "check the file permissions of your config file:\n %s" \
                 % self._filename)
         if bauble.gui is not None and bauble.gui.window is not None:
             import bauble.utils as utils
             utils.message_dialog(msg, type=gtk.MESSAGE_ERROR,
                                  parent=bauble.gui.window)
Exemplo n.º 25
0
    def start(self):
        """
        Show the connection manager.
        """
        self.create_gui()
        self.dialog.connect('response', self.on_dialog_response)
        self.dialog.connect('close', self.on_dialog_close_or_delete)
        self.dialog.connect('delete-event', self.on_dialog_close_or_delete)
        conn_list = prefs[bauble.conn_list_pref]
        if conn_list is None or len(conn_list.keys()) == 0:
            msg = _('You don\'t have any connections in your connection '\
                    'list.\nClose this message and click on "Add" to create '\
                    'a new connection.')
            utils.message_dialog(msg)
        else:
            self.set_active_connection_by_name(self.default_name)
            self._dirty = False

        self._error = True
        name = None
        uri = None
        while name is None or self._error:
            response = self.dialog.run()
            if response == gtk.RESPONSE_OK:
                name = self._get_connection_name()
                uri = self._get_connection_uri()
                if name is None:
                    msg = _('You have to choose or create a new connection ' \
                            'before you can connect to the database.')
                    utils.message_dialog(msg)
            else:
                name = uri = None
                break

        # have to remove the cell_data_func to avoid a cyclical
        # reference which would cause the ConnectionManager to not get
        # garbage collected
        cell = self.type_combo.get_cells()[0]
        self.type_combo.set_cell_data_func(cell, None)
        self.type_combo.clear()
        self.name_combo.clear()

        # just to be sure let's destroy the dialog upfront and delete
        # the params box
        self.dialog.destroy()
        del self.params_box
        obj = utils.gc_objects_by_type(CMParamsBox)
        if obj:
            warning('ConnectionManager.start(): param box leaked: %s' % obj)
        return name, uri
Exemplo n.º 26
0
 def save(self):
     try:
         f = open(self._filename, "w+")
         self.config.write(f)
         f.close()
     except Exception:
         msg = _("Bauble can't save your user preferences. \n\nPlease "
                 "check the file permissions of your config file:\n %s" %
                 self._filename)
         if bauble.gui is not None and bauble.gui.window is not None:
             import bauble.utils as utils
             utils.message_dialog(msg,
                                  type=gtk.MESSAGE_ERROR,
                                  parent=bauble.gui.window)
Exemplo n.º 27
0
    def start(self):
        if self.session.query(Family).count() == 0:
            msg = _('You must first add or import at least one Family into '
                    'the database before you can add plants.')
            utils.message_dialog(msg)
            return

        while True:
            response = self.presenter.start()
            self.presenter.view.save_state()
            if self.handle_response(response):
                break
        self.presenter.cleanup()
        self.session.close()  # cleanup session
        return self._committed
Exemplo n.º 28
0
    def start(self):
        if self.session.query(Family).count() == 0:
            msg = _('You must first add or import at least one Family into '
                    'the database before you can add plants.')
            utils.message_dialog(msg)
            return

        while True:
            response = self.presenter.start()
            self.presenter.view.save_state()
            if self.handle_response(response):
                break
        self.presenter.cleanup()
        self.session.close()  # cleanup session
        return self._committed
Exemplo n.º 29
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))
Exemplo n.º 30
0
    def start(self):
        if self.session.query(Genus).count() == 0:
            msg = _("You must first add or import at least one genus into the " "database before you can add species.")
            utils.message_dialog(msg)
            return

        while True:
            response = self.presenter.start()
            self.presenter.view.save_state()
            if self.handle_response(response):
                break

        self.presenter.cleanup()
        self.session.close()  # cleanup session
        return self._committed
Exemplo n.º 31
0
    def on_remove_button_clicked(self, button, *args):
        """
        """
        user = self.get_selected_user()
        msg = _(
            "Are you sure you want to remove user <b>%(name)s</b>?\n\n"
            "<i>It is possible that this user could have permissions "
            "on other databases not related to Ghini.</i>"
        ) % {"name": user}
        if not utils.yes_no_dialog(msg):
            return

        try:
            drop(user, revoke=True)
        except Exception, e:
            utils.message_dialog(utils.utf8(e), gtk.MESSAGE_ERROR, parent=self.get_window())
Exemplo n.º 32
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())
Exemplo n.º 33
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))
Exemplo n.º 34
0
 def save(self, force=False):
     if testing and not force:
         return
     try:
         f = open(self._filename, "w+")
         self.config.write(f)
         f.close()
     except Exception:
         msg = _("Bauble can't save your user preferences. \n\nPlease "
                 "check the file permissions of your config file:\n %s") \
             % self._filename
         if bauble.gui is not None and bauble.gui.window is not None:
             import bauble.utils as utils
             utils.message_dialog(msg, type=gtk.MESSAGE_ERROR,
                                  parent=bauble.gui.window)
         else:
             logger.error(msg)
Exemplo n.º 35
0
def remove_callback(locations):
    loc = locations[0]
    s = "%s: %s" % (loc.__class__.__name__, str(loc))
    if len(loc.plants) > 0:
        msg = _("Please remove the plants from <b>%(location)s</b> " "before deleting it.") % {"location": loc}
        utils.message_dialog(msg, gtk.MESSAGE_WARNING)
        return
    msg = _("Are you sure you want to remove %s?") % utils.xml_safe(s)
    if not utils.yes_no_dialog(msg):
        return
    try:
        session = db.Session()
        obj = session.query(Location).get(loc.id)
        session.delete(obj)
        session.commit()
    except Exception, e:
        msg = _("Could not delete.\n\n%s") % utils.xml_safe(e)
        utils.message_details_dialog(msg, traceback.format_exc(), type=gtk.MESSAGE_ERROR)
Exemplo n.º 36
0
    def create_gui(self):
        if self.working_dbtypes is None or len(self.working_dbtypes) == 0:
            msg = _("No Python database connectors installed.\n"\
                    "Please consult the documentation for the "\
                    "prerequesites for installing Bauble.")
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise Exception(msg)

        glade_path = os.path.join(paths.lib_dir(), "connmgr.glade")
        self.widgets = utils.BuilderWidgets(glade_path)

        self.dialog = self.widgets.main_dialog
        try:
            pixbuf = gtk.gdk.pixbuf_new_from_file(bauble.default_icon)
            self.dialog.set_icon(pixbuf)
        except Exception, e:
            warning(_('Could not load icon from %s' % bauble.default_icon))
            warning(traceback.format_exc())
Exemplo n.º 37
0
 def save(self, force=False):
     if testing and not force:
         return
     try:
         f = open(self._filename, "w+")
         self.config.write(f)
         f.close()
     except Exception:
         msg = _("Ghini can't save your user preferences. \n\nPlease "
                 "check the file permissions of your config file:\n %s") \
             % self._filename
         if bauble.gui is not None and bauble.gui.window is not None:
             import bauble.utils as utils
             utils.message_dialog(msg,
                                  type=gtk.MESSAGE_ERROR,
                                  parent=bauble.gui.window)
         else:
             logger.error(msg)
Exemplo n.º 38
0
 def refresh_view(self, default_vernacular_name):
     tree_model = self.treeview.get_model()
     #if len(self.model) > 0 and default_vernacular_name is None:
     vernacular_names = self.model.vernacular_names
     default_vernacular_name = self.model.default_vernacular_name
     if len(vernacular_names) > 0 and default_vernacular_name is None:
         msg = _('This species has vernacular names but none of them are '
                 'selected as the default. The first vernacular name in '
                 'the list has been automatically selected.')
         utils.message_dialog(msg)
         first = tree_model.get_iter_first()
         value = tree_model[first][0]
         path = tree_model.get_path(first)
         #self.set_model_attr('default_vernacular_name', value)
         self.model.default_vernacular_name = value
         self._dirty = True
         self.parent_ref().refresh_sensitivity()
     elif default_vernacular_name is None:
         return
Exemplo n.º 39
0
 def refresh_view(self, default_vernacular_name):
     tree_model = self.treeview.get_model()
     #if len(self.model) > 0 and default_vernacular_name is None:
     vernacular_names = self.model.vernacular_names
     default_vernacular_name = self.model.default_vernacular_name
     if len(vernacular_names) > 0 and default_vernacular_name is None:
         msg = _('This species has vernacular names but none of them are '
                 'selected as the default. The first vernacular name in '
                 'the list has been automatically selected.')
         utils.message_dialog(msg)
         first = tree_model.get_iter_first()
         value = tree_model[first][0]
         path = tree_model.get_path(first)
         #self.set_model_attr('default_vernacular_name', value)
         self.model.default_vernacular_name = value
         self._dirty = True
         self.parent_ref().refresh_sensitivity()
     elif default_vernacular_name is None:
         return
Exemplo n.º 40
0
    def init_formatter_combo(self):
        plugins = []
        for p in pluginmgr.plugins.values():
            if issubclass(p, FormatterPlugin):
                plugins.append(p)

        # we should always have at least the default formatter
        model = gtk.ListStore(str)
        #assert len(plugins) is not 0, 'No formatter plugins defined.'
        if len(plugins) == 0:
            utils.message_dialog(_('No formatter plugins defined'),
                                 gtk.MESSAGE_WARNING)
            return

        for item in plugins:
            title = item.title
            self.formatter_class_map[title] = item
            model.append([item.title])
        self.view.widgets.formatter_combo.set_model(model)
Exemplo n.º 41
0
def verify_connection(engine, show_error_dialogs=False):
    """
    Test whether a connection to an engine is a valid Bauble database. This
    method will raise an error for the first problem it finds with the
    database.

    :param engine: the engine to test
    :type engine: :class:`sqlalchemy.engine.Engine`
    :param show_error_dialogs: flag for whether or not to show message
        dialogs detailing the error, default=False
    :type show_error_dialogs: bool
    """
    ##    debug('entered verify_connection(%s)' % show_error_dialogs)
    import bauble

    if show_error_dialogs:
        try:
            return verify_connection(engine, False)
        except error.EmptyDatabaseError:
            msg = _("The database you have connected to is empty.")
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.MetaTableError:
            msg = _(
                "The database you have connected to does not have the "
                "bauble meta table.  This usually means that the database "
                "is either corrupt or it was created with an old version "
                "of Bauble"
            )
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.TimestampError:
            msg = _(
                "The database you have connected to does not have a "
                "timestamp for when it was created. This usually means "
                "that there was a problem when you created the "
                "database or the database you connected to wasn't "
                "created with Bauble."
            )
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.VersionError, e:
            msg = _(
                "You are using Bauble version %(version)s while the "
                "database you have connected to was created with "
                "version %(db_version)s\n\nSome things might not work as "
                "or some of your data may become unexpectedly "
                "corrupted."
            ) % {"version": bauble.version, "db_version": "%s" % e.version}
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
Exemplo n.º 42
0
def remove_callback(locations):
    loc = locations[0]
    s = '%s: %s' % (loc.__class__.__name__, str(loc))
    if len(loc.plants) > 0:
        msg = _('Please remove the plants from <b>%(location)s</b> '
                'before deleting it.') % {'location': loc}
        utils.message_dialog(msg, gtk.MESSAGE_WARNING)
        return
    msg = _("Are you sure you want to remove %s?") % \
        utils.xml_safe(s)
    if not utils.yes_no_dialog(msg):
        return
    try:
        session = db.Session()
        obj = session.query(Location).get(loc.id)
        session.delete(obj)
        session.commit()
    except Exception, e:
        msg = _('Could not delete.\n\n%s') % utils.xml_safe(e)
        utils.message_details_dialog(msg, traceback.format_exc(),
                                     type=gtk.MESSAGE_ERROR)
Exemplo n.º 43
0
    def init_formatter_combo(self):
        plugins = []
        for p in pluginmgr.plugins.values():
            if isinstance(p, FormatterPlugin):
                logger.debug('recognized %s as a FormatterPlugin', p)
                plugins.append(p)
            else:
                logger.debug('discarded %s: not a FormatterPlugin', p)

        # we should always have at least the default formatter
        model = gtk.ListStore(str)
        if len(plugins) == 0:
            utils.message_dialog(_('No formatter plugins defined'),
                                 gtk.MESSAGE_WARNING)
            return

        for item in plugins:
            title = item.title
            self.formatter_class_map[title] = item
            model.append([item.title])
        self.view.widgets.formatter_combo.set_model(model)
Exemplo n.º 44
0
    def init_formatter_combo(self):
        plugins = []
        for p in pluginmgr.plugins.values():
            if isinstance(p, FormatterPlugin):
                logger.debug('recognized %s as a FormatterPlugin', p)
                plugins.append(p)
            else:
                logger.debug('discarded %s: not a FormatterPlugin', p)

        # we should always have at least the default formatter
        model = gtk.ListStore(str)
        if len(plugins) == 0:
            utils.message_dialog(_('No formatter plugins defined'),
                                 gtk.MESSAGE_WARNING)
            return

        for item in plugins:
            title = item.title
            self.formatter_class_map[title] = item
            model.append([item.title])
        self.view.widgets.formatter_combo.set_model(model)
Exemplo n.º 45
0
    def on_dialog_response(self, dialog, response, data=None):
        """
        The dialog's response signal handler.
        """
        self._error = False
        if response == gtk.RESPONSE_OK:
            settings = self.params_box.get_prefs()
            dbtype = self.widgets.type_combo.get_active_text()
            if dbtype == 'SQLite':
                filename = settings['file']
                if not os.path.exists(filename):
                    path, f = os.path.split(filename)
                    if not os.access(path, os.R_OK):
                        self._error = True
                        msg = _("Bauble does not have permission to "
                                "read the directory:\n\n%s") % path
                        utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                    elif not os.access(path, os.W_OK):
                        self._error = True
                        msg = _("Bauble does not have permission to "
                                "write to the directory:\n\n%s") % path
                        utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                elif not os.access(filename, os.R_OK):
                    self._error = True
                    msg = _("Bauble does not have permission to read the "
                            "database file:\n\n%s") % filename
                    utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                elif not os.access(filename, os.W_OK):
                    self._error = True
                    msg = _("Bauble does not have permission to "
                            "write to the database file:\n\n%s") % filename
                    utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            if not self._error:
                self.save_current_to_prefs()
                prefs.prefs[prefs.picture_root_pref] = settings.get(
                    'pictures', '')
        elif response == gtk.RESPONSE_CANCEL or \
                response == gtk.RESPONSE_DELETE_EVENT:
            if not self.compare_prefs_to_saved(self.current_name):
                msg = _("Do you want to save your changes?")
                if utils.yes_no_dialog(msg):
                    self.save_current_to_prefs()

        # system-defined GtkDialog responses are always negative, in which
        # case we want to hide it
        if response < 0:
            dialog.hide()
            #dialog.emit_stop_by_name('response')

        return response
Exemplo n.º 46
0
    def on_dialog_response(self, dialog, response, data=None):
        """
        The dialog's response signal handler.
        """
        self._error = False
        if response == gtk.RESPONSE_OK:
            settings = self.params_box.get_prefs()
            dbtype = self.widgets.type_combo.get_active_text()
            if dbtype == 'SQLite':
                filename = settings['file']
                if not os.path.exists(filename):
                    path, f = os.path.split(filename)
                    if not os.access(path, os.R_OK):
                        self._error = True
                        msg = _("Bauble does not have permission to "
                                "read the directory:\n\n%s") % path
                        utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                    elif not os.access(path, os.W_OK):
                        self._error = True
                        msg = _("Bauble does not have permission to "
                                "write to the directory:\n\n%s") % path
                        utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                elif not os.access(filename, os.R_OK):
                    self._error = True
                    msg = _("Bauble does not have permission to read the "
                            "database file:\n\n%s") % filename
                    utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                elif not os.access(filename, os.W_OK):
                    self._error = True
                    msg = _("Bauble does not have permission to "
                            "write to the database file:\n\n%s") % filename
                    utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            if not self._error:
                self.save_current_to_prefs()
                prefs.prefs[prefs.picture_root_pref] = settings.get(
                    'pictures', '')
        elif response == gtk.RESPONSE_CANCEL or \
                response == gtk.RESPONSE_DELETE_EVENT:
            if not self.compare_prefs_to_saved(self.current_name):
                msg = _("Do you want to save your changes?")
                if utils.yes_no_dialog(msg):
                    self.save_current_to_prefs()

        # system-defined GtkDialog responses are always negative, in which
        # case we want to hide it
        if response < 0:
            dialog.hide()
            #dialog.emit_stop_by_name('response')

        return response
Exemplo n.º 47
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())
Exemplo n.º 48
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())
Exemplo n.º 49
0
 def on_new_button_clicked(self, *args):
     # TODO: don't set the OK button as sensitive in the name dialog
     # if the name already exists
     # TOD0: make "Enter" in the entry fire the default response
     d = gtk.Dialog(_("Formatter Name"),
                    self.view.dialog,
                    gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                    buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
     d.vbox.set_spacing(10)
     d.set_default_response(gtk.RESPONSE_ACCEPT)
     text = '<b>%s</b>' % _('Enter a name for the new formatter')
     label = gtk.Label()
     label.set_markup(text)
     label.set_padding(10, 10)
     d.vbox.pack_start(label)
     entry = gtk.Entry()
     entry.set_activates_default(True)
     d.vbox.pack_start(entry)
     d.show_all()
     names_model = self.view.widgets.names_combo.get_model()
     while True:
         if d.run() == gtk.RESPONSE_ACCEPT:
             name = entry.get_text()
             if name == '':
                 continue
             elif names_model is not None \
                     and utils.tree_model_has(names_model, name):
                 utils.message_dialog(_('%s already exists') % name)
                 continue
             else:
                 self.set_prefs_for(entry.get_text(), None, {})
                 self.populate_names_combo()
                 utils.combo_set_active_text(self.view.widgets.names_combo,
                                             name)
                 break
         else:
             break
     d.destroy()
Exemplo n.º 50
0
 def on_new_button_clicked(self, *args):
     # TODO: don't set the OK button as sensitive in the name dialog
     # if the name already exists
     # TOD0: make "Enter" in the entry fire the default response
     d = gtk.Dialog(_("Formatter Name"), self.view.dialog,
                    gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
                    buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
     d.vbox.set_spacing(10)
     d.set_default_response(gtk.RESPONSE_ACCEPT)
     text = '<b>%s</b>' % _('Enter a name for the new formatter')
     label = gtk.Label()
     label.set_markup(text)
     label.set_padding(10, 10)
     d.vbox.pack_start(label)
     entry = gtk.Entry()
     entry.set_activates_default(True)
     d.vbox.pack_start(entry)
     d.show_all()
     names_model = self.view.widgets.names_combo.get_model()
     while True:
         if d.run() == gtk.RESPONSE_ACCEPT:
             name = entry.get_text()
             if name == '':
                 continue
             elif names_model is not None \
                      and utils.tree_model_has(names_model, name):
                 utils.message_dialog(_('%s already exists') % name)
                 continue
             else:
                 self.set_prefs_for(entry.get_text(), None, {})
                 self.populate_names_combo()
                 utils.combo_set_active_text(self.view.widgets.names_combo,
                                             name)
                 break
         else:
             break
     d.destroy()
Exemplo n.º 51
0
def verify_connection(engine, show_error_dialogs=False):
    """
    Test whether a connection to an engine is a valid Bauble database. This
    method will raise an error for the first problem it finds with the
    database.

    :param engine: the engine to test
    :type engine: :class:`sqlalchemy.engine.Engine`
    :param show_error_dialogs: flag for whether or not to show message
        dialogs detailing the error, default=False
    :type show_error_dialogs: bool
    """
    ##    debug('entered verify_connection(%s)' % show_error_dialogs)
    import bauble
    if show_error_dialogs:
        try:
            return verify_connection(engine, False)
        except error.EmptyDatabaseError:
            msg = _('The database you have connected to is empty.')
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.MetaTableError:
            msg = _('The database you have connected to does not have the '
                    'bauble meta table.  This usually means that the database '
                    'is either corrupt or it was created with an old version '
                    'of Bauble')
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.TimestampError:
            msg = _('The database you have connected to does not have a '
                    'timestamp for when it was created. This usually means '
                    'that there was a problem when you created the '
                    'database or the database you connected to wasn\'t '
                    'created with Bauble.')
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.VersionError, e:
            msg = (_('You are using Bauble version %(version)s while the '
                     'database you have connected to was created with '
                     'version %(db_version)s\n\nSome things might not work as '
                     'or some of your data may become unexpectedly '
                     'corrupted.') % {
                         'version': bauble.version,
                         'db_version': '%s' % e.version
                     })
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
Exemplo n.º 52
0
def command_handler(cmd, arg):
    """
    Call a command handler.

    :param cmd: The name of the command to call
    :type cmd: str

    :param arg: The arg to pass to the command handler
    :type arg: list
    """
    logger.debug('entering ui.command_handler %s %s' % (cmd, arg))
    import gtk
    import bauble.utils as utils
    import bauble.pluginmgr as pluginmgr
    global last_handler
    handler_cls = None
    try:
        handler_cls = pluginmgr.commands[cmd]
    except KeyError, e:
        if cmd is None:
            utils.message_dialog(_('No default handler registered'))
        else:
            utils.message_dialog(_('No command handler for %s') % cmd)
            return
Exemplo n.º 53
0
def command_handler(cmd, arg):
    """
    Call a command handler.

    :param cmd: The name of the command to call
    :type cmd: str

    :param arg: The arg to pass to the command handler
    :type arg: list
    """
    import gtk
    from bauble.utils.log import error
    import bauble.utils as utils
    import bauble.pluginmgr as pluginmgr
    global last_handler
    handler_cls = None
    try:
        handler_cls = pluginmgr.commands[cmd]
    except KeyError, e:
        if cmd is None:
            utils.message_dialog(_('No default handler registered'))
        else:
            utils.message_dialog(_('No command handler for %s' % cmd))
            return
Exemplo n.º 54
0
def verify_connection(engine, show_error_dialogs=False):
    """
    Test whether a connection to an engine is a valid Ghini database. This
    method will raise an error for the first problem it finds with the
    database.

    :param engine: the engine to test
    :type engine: :class:`sqlalchemy.engine.Engine`
    :param show_error_dialogs: flag for whether or not to show message
        dialogs detailing the error, default=False
    :type show_error_dialogs: bool
    """
##    debug('entered verify_connection(%s)' % show_error_dialogs)
    import bauble
    if show_error_dialogs:
        try:
            return verify_connection(engine, False)
        except error.EmptyDatabaseError:
            msg = _('The database you have connected to is empty.')
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.MetaTableError:
            msg = _('The database you have connected to does not have the '
                    'bauble meta table.  This usually means that the database '
                    'is either corrupt or it was created with an old version '
                    'of Ghini')
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.TimestampError:
            msg = _('The database you have connected to does not have a '
                    'timestamp for when it was created. This usually means '
                    'that there was a problem when you created the '
                    'database or the database you connected to wasn\'t '
                    'created with Ghini.')
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
        except error.VersionError, e:
            msg = (_('You are using Ghini version %(version)s while the '
                     'database you have connected to was created with '
                     'version %(db_version)s\n\nSome things might not work as '
                     'or some of your data may become unexpectedly '
                     'corrupted.') %
                   {'version': bauble.version,
                    'db_version': '%s' % e.version})
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            raise
Exemplo n.º 55
0
                traceback.format_exc(),
                gtk.MESSAGE_ERROR)

    # register the plugin commands seperately from the plugin initialization
    for plugin in ordered:
        if plugin.commands in (None, []):
            continue
        for cmd in plugin.commands:
            try:
                register_command(cmd)
            except Exception, e:
                logger.debug("exception %s while registering command %s"
                             % (e, cmd))
                msg = 'Error: Could not register command handler.\n\n%s' % \
                      utils.xml_safe(str(e))
                utils.message_dialog(msg, gtk.MESSAGE_ERROR)

    # don't build the tools menu if we're running from the tests and
    # we don't have a gui
    if bauble.gui:
        bauble.gui.build_tools_menu()


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()
Exemplo n.º 56
0
    def format(objs, **kwargs):
        #        debug('format(%s)' % kwargs)
        stylesheet = kwargs['stylesheet']
        authors = kwargs['authors']
        renderer = kwargs['renderer']
        source_type = kwargs['source_type']
        use_private = kwargs['private']
        error_msg = None
        if not stylesheet:
            error_msg = _('Please select a stylesheet.')
        elif not renderer:
            error_msg = _('Please select a a renderer')
        if error_msg is not None:
            utils.message_dialog(error_msg, gtk.MESSAGE_WARNING)
            return False

        fo_cmd = renderers_map[renderer]
        exe = fo_cmd.split(' ')[0]
        if not on_path(exe):
            utils.message_dialog(
                _('Could not find the command "%(exe)s" to '
                  'start the %(renderer_name)s '
                  'renderer.') % ({
                      'exe': exe,
                      'renderer_name': renderer
                  }), gtk.MESSAGE_ERROR)
            return False

        session = db.Session()

        # convert objects to ABCDAdapters depending on source type for
        # passing to create_abcd
        adapted = []
        if source_type == plant_source_type:
            plants = sorted(get_plants_pertinent_to(objs, session=session),
                            key=utils.natsort_key)
            if len(plants) == 0:
                utils.message_dialog(
                    _('There are no plants in the search '
                      'results.  Please try another search.'))
                return False
            for p in plants:
                if use_private:
                    adapted.append(PlantABCDAdapter(p, for_labels=True))
                elif not p.accession.private:
                    adapted.append(PlantABCDAdapter(p, for_labels=True))
        elif source_type == species_source_type:
            species = sorted(get_species_pertinent_to(objs, session=session),
                             key=utils.natsort_key)
            if len(species) == 0:
                utils.message_dialog(
                    _('There are no species in the search '
                      'results.  Please try another search.'))
                return False
            for s in species:
                adapted.append(SpeciesABCDAdapter(s, for_labels=True))
        elif source_type == accession_source_type:
            accessions = sorted(get_accessions_pertinent_to(objs,
                                                            session=session),
                                key=utils.natsort_key)
            if len(accessions) == 0:
                utils.message_dialog(
                    _('There are no accessions in the search '
                      'results.  Please try another search.'))
                return False
            for a in accessions:
                if use_private:
                    adapted.append(AccessionABCDAdapter(a, for_labels=True))
                elif not a.private:
                    adapted.append(AccessionABCDAdapter(a, for_labels=True))
        else:
            raise NotImplementedError('unknown source type')

        if len(adapted) == 0:
            # nothing adapted....possibly everything was private
            # TODO: if everything was private and that is really why we got
            # here then it is probably better to show a dialog with a message
            # and raise and exception which appears as an error
            raise Exception('No objects could be adapted to ABCD units.')
        abcd_data = create_abcd(adapted, authors=authors, validate=False)

        session.close()

        logger.debug(etree.dump(abcd_data.getroot()))

        # create xsl fo file
        dummy, fo_filename = tempfile.mkstemp()
        style_etree = etree.parse(stylesheet)
        transform = etree.XSLT(style_etree)
        result = transform(abcd_data)
        fo_outfile = open(fo_filename, 'w')
        fo_outfile.write(str(result))
        fo_outfile.close()
        dummy, filename = tempfile.mkstemp()
        filename = '%s.pdf' % filename

        # TODO: checkout pyexpect for spawning processes

        # run the report to produce the pdf file, the command has to be
        # on the path for this to work
        fo_cmd = fo_cmd % ({
            'fo_filename': fo_filename,
            'out_filename': filename
        })
        logger.debug(fo_cmd)
        # TODO: use popen to get output
        os.system(fo_cmd)

        logger.debug(filename)
        if not os.path.exists(filename):
            utils.message_dialog(
                _('Error creating the PDF file. Please '
                  'ensure that your PDF formatter is '
                  'properly installed.'), gtk.MESSAGE_ERROR)
            return False
        else:
            try:
                desktop.open(filename)
            except OSError:
                utils.message_dialog(
                    _('Could not open the report with the '
                      'default program. You can open the '
                      'file manually at %s') % filename)

        return True
Exemplo n.º 57
0
        # TODO: use popen to get output
        os.system(fo_cmd)

        logger.debug(filename)
        if not os.path.exists(filename):
            utils.message_dialog(
                _('Error creating the PDF file. Please '
                  'ensure that your PDF formatter is '
                  'properly installed.'), gtk.MESSAGE_ERROR)
            return False
        else:
            try:
                desktop.open(filename)
            except OSError:
                utils.message_dialog(
                    _('Could not open the report with the '
                      'default program. You can open the '
                      'file manually at %s') % filename)

        return True


# expose the formatter
try:
    import lxml.etree as etree
except ImportError:
    utils.message_dialog('The <i>lxml</i> package is required for the '
                         'XSL report plugin')
else:
    formatter_plugin = XSLFormatterPlugin
Exemplo n.º 58
0
    display = gtk.gdk.display_get_default()
    if display is None:
        print _("**Error: Bauble must be run in a windowed environment.")
        sys.exit(1)

    import bauble.pluginmgr as pluginmgr
    import bauble.utils as utils

    # initialize threading
    gobject.threads_init()

    try:
        import bauble.db as db
    except Exception, e:
        utils.message_dialog(utils.xml_safe(e), gtk.MESSAGE_ERROR)
        sys.exit(1)

    # declare module level variables
    global gui, default_icon, conn_name

    default_icon = os.path.join(paths.lib_dir(), "images", "icon.svg")

    open_exc = None
    # open default database
    if uri is None:
        from bauble.connmgr import start_connection_manager
        while True:
            if not uri or not conn_name:
                conn_name, uri = start_connection_manager()
                if conn_name is None:
Exemplo n.º 59
0
class CSVImporter(Importer):
    """imports comma separated value files into a Bauble database.

    It imports multiple files, each of them equally named as the bauble
    database tables. The bauble tables dependency graph defines the correct
    import order, each file being imported will completely replace any
    existing data in the corresponding table.

    The CSVImporter imports the rows of the CSV file in chunks rather than
    one row at a time.  The non-server side column defaults are determined
    before the INSERT statement is generated instead of getting new defaults
    for each row.  This shouldn't be a problem but it also means that your
    column default should change depending on the value of previously
    inserted rows.

    """
    def __init__(self):
        super(CSVImporter, self).__init__()
        self.__error = False  # flag to indicate error on import
        self.__cancel = False  # flag to cancel importing
        self.__pause = False  # flag to pause importing
        self.__error_exc = False

    def start(self, filenames=None, metadata=None, force=False):
        '''start the import process. this is a non blocking method: we queue
        the process as a bauble task. there is no callback informing whether
        it is successfully completed or not.

        '''
        if metadata is None:
            metadata = db.metadata  # use the default metadata

        if filenames is None:
            filenames = self._get_filenames()
        if filenames is None:
            return

        bauble.task.queue(self.run(filenames, metadata, force))

    @staticmethod
    def _toposort_file(filename, key_pairs):
        """
        filename: the csv file to sort

        key_pairs: tuples of the form (parent, child) where for each
        line in the file the line[parent] needs to be sorted before
        any of the line[child].  parent is usually the name of the
        foreign_key column and child is usually the column that the
        foreign key points to, e.g ('parent_id', 'id')
        """
        f = open(filename, 'rb')
        reader = UnicodeReader(f, quotechar=QUOTE_CHAR, quoting=QUOTE_STYLE)

        # create a dictionary of the lines mapped to the child field
        bychild = {}
        for line in reader:
            for parent, child in key_pairs:
                bychild[line[child]] = line
        f.close()
        fields = reader.reader.fieldnames
        del reader

        # create pairs from the values in the lines where pair[0]
        # should come before pair[1] when the lines are sorted
        pairs = []
        for line in bychild.values():
            for parent, child in key_pairs:
                if line[parent] and line[child]:
                    pairs.append((line[parent], line[child]))

        # sort the keys and flatten the lines back into a list
        sorted_keys = utils.topological_sort(bychild.keys(), pairs)
        sorted_lines = []
        for key in sorted_keys:
            sorted_lines.append(bychild[key])

        # write a temporary file of the sorted lines
        import tempfile
        tmppath = tempfile.mkdtemp()
        head, tail = os.path.split(filename)
        filename = os.path.join(tmppath, tail)
        tmpfile = open(filename, 'wb')
        tmpfile.write('%s\n' % ','.join(fields))
        #writer = UnicodeWriter(tmpfile, fields, quotechar=QUOTE_CHAR,
        writer = csv.DictWriter(tmpfile,
                                fields,
                                quotechar=QUOTE_CHAR,
                                quoting=QUOTE_STYLE)
        writer.writerows(sorted_lines)
        tmpfile.flush()
        tmpfile.close()
        del writer
        return filename

    def run(self, filenames, metadata, force=False):
        '''
        A generator method for importing filenames into the database.
        This method periodically yields control so that the GUI can
        update.

        :param filenames:
        :param metadata:
        :param force: default=False
        '''
        transaction = None
        connection = None
        self.__error_exc = BaubleError(_('Unknown Error.'))

        try:
            # user a contextual connect in case whoever called this
            # method called it inside a transaction then we can pick
            # up the parent connection and the transaction
            connection = metadata.bind.connect()
            transaction = connection.begin()
        except Exception, e:
            msg = _('Error connecting to database.\n\n%s') % \
                utils.xml_safe(e)
            utils.message_dialog(msg, gtk.MESSAGE_ERROR)
            return

        # create a mapping of table names to filenames
        filename_dict = {}
        for f in filenames:
            path, base = os.path.split(f)
            table_name, ext = os.path.splitext(base)
            if table_name in filename_dict:
                safe = utils.xml_safe
                values = dict(table_name=safe(table_name),
                              file_name=safe(filename_dict[table_name]),
                              file_name2=safe(f))
                msg = _('More than one file given to import into table '
                        '<b>%(table_name)s</b>: %(file_name)s, '
                        '(file_name2)s') % values
                utils.message_dialog(msg, gtk.MESSAGE_ERROR)
                return
            filename_dict[table_name] = f

        # resolve filenames to table names and return them in sorted order
        sorted_tables = []
        for table in metadata.sorted_tables:
            try:
                sorted_tables.insert(0, (table, filename_dict.pop(table.name)))
            except KeyError, e:
                # table.name not in list of filenames
                pass
Exemplo n.º 60
0
    command = 'exxml'

    def __call__(self, cmd, arg):
        logger.debug('XMLExportCommandHandler(%s)' % arg)
        exporter = XMLExporter()
        logger.debug('starting')
        exporter.start(arg)
        logger.debug('started')


class XMLExportTool(pluginmgr.Tool):
    category = _("Export")
    label = _("XML")

    @classmethod
    def start(cls):
        c = XMLExporter()
        c.start()


class XMLImexPlugin(pluginmgr.Plugin):
    tools = [XMLExportTool]
    commands = [XMLExportCommandHandler]


try:
    import lxml.etree as etree
except ImportError:
    utils.message_dialog('The <i>lxml</i> package is required for the '
                         'XML Import/Exporter plugin')