Source

python-fu-dump / dump.py

from gimpfu import *
from string import Template
import gtk
import os
import collections
import ctypes
import unicodedata
import re
import pprint

"""
in the documentation, but not defined in gimpfu
PF_REGION:"PF_REGION"
"""
VAR_TYPES = {PF_INT8:"PF_INT8",PF_INT16:"PF_INT16",PF_INT32:"PF_INT32",PF_INT:"PF_INT",PF_FLOAT:"PF_FLOAT",PF_STRING:"PF_STRING",PF_VALUE:"PF_VALUE",PF_COLOR:"PF_COLOR",PF_COLOUR:"PF_COLOUR",PF_IMAGE:"PF_IMAGE",PF_LAYER:"PF_LAYER",PF_CHANNEL:"PF_CHANNEL",PF_DRAWABLE:"PF_DRAWABLE",PF_TOGGLE:"PF_TOGGLE",PF_BOOL:"PF_BOOL",PF_RADIO:"PF_RADIO",PF_SLIDER:"PF_SLIDER",PF_SPINNER:"PF_SPINNER",PF_ADJUSTMENT:"PF_ADJUSTMENT",PF_FONT:"PF_FONT",PF_FILE:"PF_FILE",PF_BRUSH:"PF_BRUSH",PF_PATTERN:"PF_PATTERN",PF_GRADIENT:"PF_GRADIENT",PF_PALETTE:"PF_PALETTE"}

PROC_TYPES = {PLUGIN:"PROC_PLUG_IN",EXTENSION:"PROC_EXTENSION",TEMPORARY:"PROC_TEMPORARY"}

PROC_CSS = """html, body
{
        width:100%;
        height:100%;
        margin:0px;
}

body
{
        width:578px;
        margin:24px auto 0px 36px;
}

p, table
{
        margin:0px 0px 0px 12px;
}

nav
{
        display:block;
        margin-bottom:6px;
        text-align:center;
}

h1
{
        margin-top:0px;
}

h1, h4
{
        margin-bottom:0px;
}

div#author
{
        text-align:right;
        font-style:italic;
}

span.date
{
        font:bold 14px Monospace,small-caps;
}

table
{
        font-family:'Trebuchet MS', Arial, Helvetica, sans-serif;
        width:100%;
        border-collapse:collapse;
}

table td, table th 
{
        font-size:1em;
        border:1px solid SlateGray;
        padding:3px 7px 2px 7px;
}

table th
{
        font-size:1.1em;
        text-align:left;
        padding-top:5px;
        padding-bottom:4px;
        background-color:LightSlateGray;
        color:#ffffff;
}

table tr.alt td 
{
        color:#000000;
        background-color:#C9CFD6;
}
"""
PROC_HTML = """<!DOCTYPE html>
<html>
        <head>
                <title>pdb: ${proc_name}</title>

                <meta name="description" content="${proc_blurb}">
                <meta name="author" content="Code Fox">
                <meta charset="UTF-8">

                <link rel="stylesheet" type="text/css" href="proc.css">
        </head>
        <body>
                <div style="display:inline-block;">
                        <h1>
                                ${proc_name}
                        </h1>
                        <div id="author">
                                ${proc_author}
                        </div>
                </div>
                <hr style="margin-bottom:0px;"/>
                <nav>
                        <a href="${prev_link}" style="float:left;">previous</a>
                        <a href="${index_link}">index</a>
                        <a href="${next_link}" style="float:right;">next</a>
                </nav>
                <p id="copyright" style="margin:0">
                        <span class="date">${proc_date}</span><br>
                        ${proc_copyright}
                </p>
                <h4>Description</h4>
                <p id="description">
                        ${proc_blurb}
                </p>
                <h4>Help</h4>
                <p id="help">
                        ${proc_help}
                </p>
                <hr />
                <h4>Type</h4>
                <p id="type">
                        ${proc_type}
                </p>
                <h4>Parameters</h4>
                <table id="parameters">
                        <thead>
                                <tr>
                                        <th>Type</th>
                                        <th>Name</th>
                                        <th>Description</th>
                                </tr>
                        </thead>
                        <tbody>
                                ${parameters}
                        </tbody>
                </table>
                <h4>Return</h4>
                <table id="return">
                        <thead>
                                <tr>
                                        <th>type</th>
                                        <th>name</th>
                                        <th>description</th>
                                </tr>
                        </thead>
                        <tbody>
                                ${results}
                        </tbody>
                </table>
                <hr style="margin-bottom:0px;" />
                <nav>
                        <a href="${index_link}" style="width:100%; text-align:center;">index</a>
                </nav>
        </body>
</html>
"""
TR_HTML = """
                                <tr ${class}>
                                        <td>
                                                ${type}
                                        </td>
                                        <td>
                                                ${name}
                                        </td>
                                        <td>
                                                ${desc}
                                        </td>
                                </tr>

"""
INDEX_TEMPLATE = """
"""

def escape(html):
        """
        Returns the given HTML with ampersands, quotes and angle brackets encoded.
        """
        html = unicode(html)
        html = html.replace('&', '&amp;')
        html = html.replace('<', '&lt;')
        html = html.replace('>', '&gt;')
        html = html.replace('"', '&quot;')
        html = html.replace("'", '&#39;')

        return html.encode('ascii', 'ignore')

def slugify(value):
        """
        Normalizes string, converts to lowercase, removes non-alpha characters,
        and converts spaces to hyphens.

        Based on code in: Django
        """
        value = unicodedata.normalize('NFKD', unicode(value))
        value = value.encode('ascii', 'ignore')
        value = re.sub('[^\w\s-]', '', value).strip().lower()
        value = re.sub('[-\s]+', '-', value)
        return value

def get_dir() :
        MessageBox = ctypes.windll.user32.MessageBoxA
        response = ""

        # Check for new pygtk: this is new class in PyGtk 2.4
        if (gtk.pygtk_version < (2,3,90)) :
                MessageBox(None, "This plugin requires PyGtk 2.3.90 or later", "Error", 0)
                return response

        dialog = gtk.FileChooserDialog(
                "Dump to...",
                None,
                gtk.FILE_CHOOSER_ACTION_OPEN,
                (
                        gtk.STOCK_CANCEL,
                        gtk.RESPONSE_CANCEL,
                        gtk.STOCK_OPEN,
                        gtk.RESPONSE_OK
                )
        )
        dialog.set_default_response(gtk.RESPONSE_OK)
        dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)

        if (dialog.run() == gtk.RESPONSE_OK) :
                response = dialog.get_filename()
        dialog.destroy()

        return response

def prepare(root) :
        # create sub directory if it doesnt exist
        outDirectory = os.path.join(
                        root,
                        "pdb"
        )

        if not os.path.exists(outDirectory):
                os.makedirs(outDirectory)

        return outDirectory

def dump_css(outFile) :

        with open(outFile,'w') as f:
                f.write(PROC_CSS)

        return None

def dump_var_type(t) :
        if (t not in VAR_TYPES) :
                return "unknown"

        return VAR_TYPES[t]

def dump_proc_type(t) :
        if (t not in PROC_TYPES) :
                return "unknown"

        return PROC_TYPES[t]

def dump_table(lst) :
        row = dict()
        html = ""
        alt = False
        for item in lst :
                row["class"] = ""
                if (True == alt) :
                        row["class"] = ' class="alt"'
                row["type"] = dump_var_type(item[0])
                row["name"] = escape(item[1])
                row["desc"] = escape(item[2])

                html += Template(TR_HTML).safe_substitute(row)
                alt = not alt

        return html

def dump_proc(proc, outFile, mode, links) :
        d = dict()

        d["prev_link"] = links[0]
        d["index_link"] = links[1]
        d["next_link"] = links[2]

        d["proc_name"] = escape(proc.proc_name)
        d["proc_author"] = escape(proc.proc_author)
        d["proc_date"] = escape(proc.proc_date)
        d["proc_copyright"] = escape(proc.proc_copyright)
        d["proc_blurb"] = escape(proc.proc_blurb)
        d["proc_help"] = escape(proc.proc_help)
        d["proc_type"] = dump_proc_type(escape(proc.proc_type))

        d["parameters"] = dump_table(proc.params)
        d["results"] = dump_table(proc.return_vals)

        with open(outFile, mode) as f :
                f.write(Template(PROC_HTML).safe_substitute(d))

        return None

def fname(pname) :
        return "%s.html"%(slugify(pname))

def dump_pdb() :
        MessageBox = ctypes.windll.user32.MessageBoxA

        root = get_dir()
        if("" == root) :
                return None

        outDirectory = prepare(root)
        dump_css(os.path.join(
                outDirectory,
                "proc.css"
        ))

        # loop through PDB
        procs = gimp.pdb.query()
        procs.sort()

        links = [fname(procs[-1]), "../index.html", ""]
        for i in range(len(procs)) :
                name = procs[i]
                outFile = os.path.join(
                        outDirectory,
                        fname(name)
                )
                links[2] = fname(procs[(i+1) % len(procs)])
                dump_proc(pdb[name], outFile, 'w+', links)
                links[0] = os.path.basename(outFile)
                #break

        # todo: write index file

        return None

register(
        #name
        "dump-pdb",
        #blurb
        "dumps pdb database to HTML",
        #help
        "man up buttercup",
        #author
        "codefox",
        #copyright
        "MIT license => rtfm",
        #date
        "Jan 29, 2013",
        #menu path
        "<Toolbox>/Help/Procedure Dump",
        #image types
        None,
        #params
        [],
        #results
        [],
        #function
        dump_pdb
)

main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.