File nodes quickly and easily

This @button code adds a filer button. The intended use is this: you have a long list of nodes (web bookmarks, most likely) that need to be filed at the appropriate place in a tree (categories, subcategories). Normally this is cumbersome, you have to navigate to your list, copy or cut a node, navigate to the correct location, paste it, navigate back to your list, etc. This button makes it much simpler.

Pressing the filer button adds the following buttons:

filehere
File the node here, either after this node, or, if this node is expanded, as the first child of this node
filein
File the node as the first child of this node
skipit
Leave the node on the list of nodes to file
dumpit
Move the node to a sublist of nodes called 'Dumped nodes'
showit
If you're filing web bookmarks, the showit button loads the url in the node, in case you don't remember what it is. The showit button is compatible with @url http://example.com/ headline urls, and first line of the body urls as used by the bookmarks plugin.

So now you just pick the first node in the list of nodes needing filing and click filer. The node you're currently filing is listed in the log window. Navigate to the correct location for that node and click filehere, a clone is pasted there for you. The next node to file is listed in the log window... navigate to its correct home... and repeat.

When you're done just delete Filed nodes and Dumped nodes lists if your satisfied that all went well. Dumped nodes is only created if at least one node is dumped.

Here's the code you should include in the outline, with a node headline of @button filer:

# updated 2007-12-19 3:47pm CDT

from mod_scripting import scriptingController

class Filer(object):
    def __init__(self, c):
        self.c = c
        self.current = c.currentPosition()
        self.sc = scriptingController(c)
        self.buttons = []
        btxt = (('FileHere', self.fileIt, 'File the next unfiled node here'),
                ('FileIn', self.fileIn, 'File the next unfiled node as child'),
                ('SkipIt', self.advance, 'Leave node unfiled'),
                ('DumpIt', self.dumpIt, 'Move node to cull list'),
                ('ShowIt', self.showIt, 'Show url in node'),
                )
        for label, method, descrip in btxt:
            self.buttons.append(
                self.sc.createIconButton(
                    text = label,
                    command = method,
                    shortcut = None,
                    statusLine = descrip,
                    bg = "LightBlue"
                )
            )
        c.beginUpdate()
        try:
            self.filed = self.current.insertAfter()
            c.setChanged(True)
            self.filed.setHeadString('Filed nodes')
            self.dumped = None
            self.current.moveAfter(self.filed)
            self.report()
        finally:
            c.endUpdate()
    def report(self):
        g.es('Now filing: %s' % self.current.headString())
    def advance(self):
        try:
            self.current = self.current.next()
            if not self.current.v: raise Exception
        except:
            g.es('No more nodes, removing the buttons')
            for i in self.buttons: self.sc.deleteButton(i)
            c.setChanged(True)
            c.redraw_now()
        else:
            self.report()
    def fileIn(self): self.fileIt(asChild = True)
    def fileIt(self, asChild = False):
        c.beginUpdate()
        try:
            clone = self.current.clone()
            where = c.currentPosition()
            if asChild or where.isExpanded():
                clone.moveToFirstChildOf(where)
            else:
                clone.moveAfter(where)
            toMove = self.current.copy()
            self.advance()
            toMove.moveToLastChildOf(self.filed)
        finally:
            c.endUpdate()
    def showIt(self):
        x = self.current.headString().strip()
        if x.startswith('@url'):
            url = x[4:].strip()
        else:
            lines = self.current.bodyString().split('\n')
            url = lines and lines[0].strip() or ''
        if not g.doHook("@url1",c=c,p=self.current,v=self.current,url=url):
            c.frame.handleUrlInUrlNode(url)
    def dumpIt(self):
        c.beginUpdate()
        try:
            if self.dumped == None:
                self.dumped = self.filed.insertAfter()
                self.dumped.setHeadString('Dumped nodes')
            toMove = self.current.copy()
            self.advance()
            toMove.moveToLastChildOf(self.dumped)
        finally:
            c.endUpdate()

filer = Filer(c)

That's it.