Example #1
0
 def prevalidate(self):
     '''
     make sure we are in the right kind of folder
     '''
     node = hub.tree.focus_element()
     return hub.is_branch(
         node) and node[1] not in hub.coredb.special_branch_ids
Example #2
0
    def move_selected(self, node=None):
        '''
        move selected items into current folder. Reset selected to 0.
        '''
        if node is None:  # invocation from menu will trigger this case
            node = hub.tree.focus_element()

        assert hub.is_branch(node)
        node_id = node[1]

        # get hold of all selected folders
        stmt = 'update branches set parent_id=(?), selected=0 where selected=1'
        c = self._db.execute(stmt, [node_id])
        moved_items = c.rowcount

        errors = 0

        stmt = '''
               update reflink set branch_id=(?), selected = 0
               where selected=1
               and not ref_id in
                   (select ref_id from reflink where branch_id=(?))
               '''
        try:
            c = self._db.execute(stmt, [node_id, node_id])
            moved_items += c.rowcount
        except IntegrityError:
            hub.show_errors('Oopsie - something bad just happened')

        if not moved_items:
            hub.show_errors('Nothing was moved')
        else:
            self._db.commit()
            hub.clear_cache()
            hub.tree.refresh()
Example #3
0
    def __getitem__(self, pos):
        '''
        obtain one tree item for display. Must check back with the database
        to look for updates.
        '''
        text_tuple, selected = hub.get_node_display_info(pos)
        key, title = text_tuple

        if selected == 0:
            low, high = 'body', 'focus'
        elif selected == hub.SELECTED:
            low, high = 'selected body', 'selected focus'
        else:
            low, high = 'in selection body', 'in selection focus'

        nodeinfo = str(pos) if self.debug else ''

        if title is None or hub.is_branch(pos):
            return widgets.FocusableText(key + nodeinfo, low, high)
        else:
            widget = urwid.Pile([
                ReferenceDisplay(key, nodeinfo + title, low, high),
                urwid.Divider()
            ])
            return widget
Example #4
0
 def prevalidate(self):
     '''
     make sure we are in the right kind of folder
     '''
     node = hub.tree.focus_element()
     return hub.is_branch(node) \
            and (node[1] not in hub.coredb.special_branch_ids \
                 or hub.coredb.special_branch_names['References'] == node[1])
Example #5
0
    def copy_selected(self, node=None):
        '''
        copy selected references and folders into current folder. Should we also
        deselect? Because if we don't, it's less work, but might be annoying.

        Let's wait and see. Actually, we need a 'deselect all' anyway, so we
        might just call that at the end.
        '''
        if node is None:  # invocation from menu will trigger this case
            node = hub.tree.focus_element()

        assert hub.is_branch(node)
        node_id = node[1]

        # get hold of all selected folders
        stmt = 'select * from branches where selected=1'
        branches = self._db.execute(stmt).fetchall()

        errors = []
        success = 0

        for branch in branches:
            b = (hub.BRANCH, branch['branch_id'], branch['parent_id'])
            try:
                new_id = self.clone_branch(b, node_id)
                success += 1
            except RefdbError as e:
                errors.append(e.message)

        # now on to the references
        stmt = 'select ref_id from reflink where selected=1'
        ref_ids = self._db.execute(stmt).fetchvalues()

        failed_refs = 0

        for ref_id in ref_ids:
            try:
                self._db.insert('reflink',
                                dict(ref_id=ref_id, branch_id=node_id))
                success += 1
            except IntegrityError:
                failed_refs += 1

        if success:
            self._db.commit()
            hub.clear_cache()
            hub.tree.refresh()

        if failed_refs:
            suffix = '' if failed_refs == 1 else 's'
            errors.append("%s duplicate reference%s not copied" %
                          (failed_refs, suffix))

        if errors:
            hub.show_errors(errors)

        if success == len(errors) == 0:
            hub.show_errors('Nothing was selected')
Example #6
0
 def toggle_refs(self):
     '''
     show/hide refs within the tree
     '''
     node = self.focus_element()
     branch = node if hub.is_branch(node) else hub.get_parent_node(node)
     hub.toggle_branches_only()
     self.refresh()
     try:
         self.set_focus(branch)
     except:  # strange things happen if we press F3 immediately after program start
         pass
Example #7
0
    def select_refs(self, node=None):
        '''
        select references immediately in this folder, but not sub-folders
        '''
        if node is None:  # invocation from menu will trigger this case
            node = hub.tree.focus_element()

        assert hub.is_branch(node)
        node_id = node[1]

        stmt = 'update reflink set selected = 1 where branch_id=(?) and selected = 0'
        c = self._db.execute(stmt, [node_id])

        if c.rowcount != 0:
            self._db.commit()
            hub.clear_cache()
            hub.tree.refresh()
Example #8
0
    def exists_folder(self, parent, subfolder_name):
        '''
        check if a folder name is already present inside a target parent folder.
        parent may be a node or just a branch_id.
        '''
        try:
            parent_id = int(parent)
            stmt = "select parent_id from branches where branch_id = (?)"
            ppid = self._db.execute(stmt, [parent_id]).fetchvalue()
            parent = (hub.BRANCH, parent_id, ppid)
        except TypeError:
            pass  # assume it's already a tuple

        assert hub.is_branch(parent)

        branch_names = [
            hub.get_branch_title(b) for b in self.get_child_branches(parent)
        ]
        return subfolder_name in branch_names
Example #9
0
    def flatten_folder(self, node=None):
        '''
        - recursively collect all references below this folder
        - empty out this folder
        - insert the collect the references back into it.
        '''
        if node is None:  # invocation from menu will trigger this case
            node = hub.tree.focus_element()

        assert hub.is_branch(node)
        node_id = node[1]

        # collect all references from nested folders
        stmt = '''
        with recursive branch_set(i)
        as ( select branch_id from branches where parent_id = (?)
                union select branch_id from branches, branch_set
                    where branches.parent_id = branch_set.i
            )
        select distinct(ref_id) from reflink
        where branch_id in branch_set
        '''
        nested_references = self._db.execute(stmt, [node_id]).fetchvalues()

        # now, delete all nested folders
        stmt = '''delete from branches where parent_id=(?)'''
        self._db.execute(stmt, [node_id])

        # collect any remaining references
        stmt = "select ref_id from reflink where branch_id=(?)"
        direct_references = self._db.execute(stmt, [node_id]).fetchvalues()

        # finally, insert all references directly into parent, omitting duplicates
        remaining = set(nested_references) - set(direct_references)
        for ref in remaining:
            self._db.insert('reflink',
                            dict(ref_id=ref, branch_id=node_id, selected=0))

        # finish up
        self._db.commit()
        hub.clear_cache()
        hub.tree.refresh()
Example #10
0
    def add_folder(self, parent, new_name):
        '''
        not really a clipboard operation itself, but related.

        Should we guard against duplicated names in same folder? I guess so.
        '''
        if not new_name:
            hub.show_errors("Folder name cannot be empty")
            return

        if not hub.is_branch(parent):
            hub.show_errors("Cannot create folder inside a reference")
            return

        parent_id = parent[1]

        if self.exists_folder(parent, new_name):
            hub.show_errors("Subfolder '%s' already exists - aborting" %
                            new_name)
            return

        c = self._db.insert('branches', dict(name=new_name,
                                             parent_id=parent_id))
        new_id = c.lastrowid
        self._db.commit()

        # clearing the cache shouldn't be needed, but it is - deleted folder nodes
        # somehow linger, and if an id gets reused, the zombies reappear
        hub.clear_cache()
        hub.tree.refresh()

        # now, we should be able to construct the new node signature without going
        # back to the database
        new_node = (hub.BRANCH, new_id, parent_id)
        hub.tree.set_focus(new_node)
        hub.tree.add_to_history(new_node)
Example #11
0
    def add_reference(self, new_data, node=None, single_mode=True):
        '''
        What do we do here if constraints are violated? I think in the case of
        missing or reduplicated bibtex keys we just concatenate a random string
        and try again. For title, we can just supply a dummy title.

        single_mode: we also use this as a backend for importers, so we
        don't commit and display errors right here in that case.
        '''
        if node is None:
            node = hub.tree.focus_element()
        assert hub.is_branch(node)

        values = [_f for _f in list(new_data.values()) if _f]

        if not values:
            hub.show_errors("No data provided - aborting.")
            return

        # I guess from here we will insert something, even if it is crap.
        # we just keep track of the errors and show them at the end.
        errors = []

        orig_bibtexkey = new_data.get('bibtexkey')
        new_bibtexkey = new_data['bibtexkey'] = self.make_bibtex_key(new_data)

        #if orig_bibtexkey and orig_bibtexkey != new_bibtexkey: don't nag the user
        #hub.show_message("bibtexkey '%s' changed to '%s'" % (orig_bibtexkey, new_bibtexkey))

        new_data['title'] = new_data['title'].rstrip('.')

        if not new_data['title']:
            new_data['title'] = "Title can't be empty -- please fix"
            errors.append(new_data['title'])

        if new_data['reftype'] not in self.ref_types:
            errors.append("reftype was empty or faulty - set to 'article'")
            new_data['reftype'] = 'article'

        # at this point, we should have everything in place. Now, we can still fail to
        # insert a reference if we have a duplicate bibtexkey, in which case we need to fix.
        # I suppose I will fix it up with appending a short random string.

        ref_data = dict(reftype_id=self.ref_types[new_data['reftype']],
                        title=new_data['title'],
                        bibtexkey=new_bibtexkey)

        c = self._db.insert('refs', ref_data)
        ref_id = c.lastrowid

        try:
            errors += self.update_reference(dict(ref_id=ref_id),
                                            new_data,
                                            add_reference=True)
        except IntegrityError:
            errors.append("Record '%s...' not imported (likely duplicate)" %
                          new_data['title'][:50])
            # also need to revert partial import
            self._db.execute('delete from refs where ref_id=(?)', [ref_id])
            return errors

        # Associate the new reference with the current branch
        branch_id = node[1]

        for branch_id in (node[1], self.recently_added_id):
            self._db.insert('reflink', dict(ref_id=ref_id,
                                            branch_id=branch_id))

        if single_mode:
            self._db.commit()
            hub.refresh_tree_item(node)

            if errors:
                hub.show_errors(errors)

        else:  # collect errors for display later on.
            return errors