""" MoinMoin - VisualSiteMap action Idea is based on the webdot.py action. More or less redid it from scratch. Differs from the webdot action in several ways: * Uses the dot executable, not webdot, since webdot's not available on windows. * All links up to the search depth are displayed. * There's no maximal limit to the displayed nodes. * Nodes are marked during depth first visit, so each node is visited only once. * The visit method in class LocalSiteMap gets the whole tree as parameter. That way additional treenode information may be shown in the graph. * All edges between nodes contained in the graph are displayed, even if MAX_DEPTH is exceeded that way. * Optional depth controls * Nodes linked more then STRONG_LINK_NR times are highlighted using the STRONG_COLOR * Search depth is configurable Add this to your stylesheet: img.sitemap { border-width: 1; border-color: #000000; } 07.10.2004 * Maximum image size can be configured * Output image format is configurable * David Linke changed the output code (print() -> request.write()) * Changed link counting algorithm to get the depth controls right. 08.10.2004 * IE caching problem with depth controls resolved. Now the current search depth is part of the file names. * Problems with pagenames containing non ASCII characters fixed. $Id$ """ ################################################################## # Be warned that calculating large graphs may block your server! # # So be careful with the parameter settings. # ################################################################## # Imports import string,sys,re,os from MoinMoin import config, wikiutil, user from MoinMoin.Page import Page # Graph controls. DEFAULT_DEPTH = 2 STRONG_LINK_NR = 4 # Optional controls for interactive modification of the search depth. DEPTH_CONTROL = 0 MAX_DEPTH = 4 # This should be a public path on your web server. The dot files, images and map files are created in this directory and # served from there. CACHE_DIR = "C:/DocumentRoot/cache/"; CACHE_URL = "http://my-server/cache/"; # Absolute location of the dot (or neato) executable. DOT_EXE = "C:/Programme/ATT/GraphViz/bin/dot.exe"; # Desired image format (eg. png, jpg, gif - see the dot documentation) OUTPUT_FORMAT = "png" # Maximum output size in inches. Set to None to disable size limitation. # OUTPUT_SIZE="8,4" sets maximum width to 8, maximum height to 4 inches. OUTPUT_SIZE="10,10" # Colors of boxes and edges. BOX_COLOR ="#E0F0FF" ROOT_COLOR = "#FFE0E0" STRONG_COLOR = "#E0FFE0" EDGE_COLOR ="#888888" # Categories are filtered in some way. CATEGORY_STRING = "^Kategorie" # Code starts here def execute(pagename, request): _ = request.getText maxdepth = int(DEFAULT_DEPTH) if DEPTH_CONTROL and request.form.has_key('depth'): maxdepth = int(request.form['depth'][0]) if int(maxdepth) > int(MAX_DEPTH): maxdepth = MAX_DEPTH request.http_headers() wikiutil.send_title(request, _('Visual Map of %s') % (pagename), pagename=pagename) baseurl = request.getBaseURL() wikiname = wikiutil.quoteWikiname(pagename) dotfilename = '%s/%s_%s.dot' % (CACHE_DIR, wikiname, maxdepth) imagefilename = '%s/%s_%s.%s' % (CACHE_DIR, wikiname, maxdepth, OUTPUT_FORMAT) imageurl = '%s/%s_%s.%s' % (CACHE_URL, wikiname, maxdepth, OUTPUT_FORMAT) mapfilename = '%s/%s_%s.cmap' % (CACHE_DIR, wikiname, maxdepth) dotfile = open(dotfilename,'w') dotfile.write('digraph G {\n') if OUTPUT_SIZE: dotfile.write(' size="%s"\n' % OUTPUT_SIZE) dotfile.write(' ratio=compress;\n') dotfile.write(' URL="%s";\n' % wikiname) dotfile.write(' overlap=false;\n') dotfile.write(' concentrate=true;\n') dotfile.write(' edge [color="%s"];\n' % EDGE_COLOR) dotfile.write(' node [URL="%s/\N", ' % baseurl) dotfile.write('fontcolor=black, fontname=%s , fontsize=%s, style=filled, color="%s"]\n' % ("arial","8", BOX_COLOR)) dotfile.write(LocalSiteMap(pagename, maxdepth).output(request)) dotfile.write('}\n') dotfile.close() os.system('%s -T%s -o%s %s' % (DOT_EXE, OUTPUT_FORMAT, imagefilename, dotfilename)) os.system('%s -Tcmap -o%s %s' % (DOT_EXE, mapfilename, dotfilename)) request.write('
') if maxdepth > 1: request.write('Less' % (baseurl, linkname, maxdepth-1)) else: request.write('Less') request.write(' | ') if maxdepth < MAX_DEPTH: request.write('More' % (baseurl, linkname, maxdepth+1)) else: request.write('More') request.write('
') request.write('Search depth is %s. Nodes linked more than %s times are highlighted.
' % (maxdepth, STRONG_LINK_NR)) wikiutil.send_footer(request, pagename) class LocalSiteMap: def __init__(self, name, maxdepth): self.name = name self.result = [] self.maxdepth = maxdepth def output(self, request): pagebuilder = GraphBuilder(request, self.maxdepth) root = pagebuilder.build_graph(self.name) # count links # print '