Attachment 'VisualSiteMap.py'

Download

   1 """
   2     MoinMoin - VisualSiteMap action
   3 
   4     Idea is based on the webdot.py action.
   5     
   6     More or less redid it from scratch. Differs from the webdot action in several ways:
   7     * Uses the dot executable, not webdot, since webdot's not available on windows.
   8     * All links up to the search depth are displayed. So you get the full map, not only a part of it.
   9     * There's no maximal limit to the displayed nodes. Again, I wanted the full map.
  10     * Nodes are marked during depth first visit, so each node is visited only once.
  11     * The visit method in class LocalSiteMap gets the whole tree as parameter. That way additional treenode information
  12       may be shown in the graph.
  13     * All edges between nodes contained in the graph are displayed, even if MAX_DEPTH is exceeded that way.
  14     * Search depth may be controlled through the command line argument 'depth': ?action=VisualSiteMap&depth=1
  15     * Experimental: Optional depth controls (set DEPTH_CONTROL = 1 and give it a try)
  16     * Nodes linked more then STRONG_LINK_NR times are highlighted using the STRONG_COLOR
  17 
  18     Add this to your stylesheet:
  19     img.sitemap
  20     {
  21       border-width: 1;
  22       border-color: #000000;
  23     }
  24 
  25     $Id$
  26 """
  27     
  28 
  29 # Imports
  30 import string,sys,re,os;
  31 from MoinMoin import config, wikiutil, webapi, user;
  32 from MoinMoin.Page import Page;
  33 
  34 # Graph controls
  35 DEFAULT_DEPTH = 2;
  36 STRONG_LINK_NR = 4;
  37 ROOT_URL   = "/MyWiki";
  38 
  39 # Experimental: Optional controls for interactive modification of the search depth.
  40 DEPTH_CONTROL = 0;
  41 MAX_DEPTH  = 4;
  42 
  43 # This should be a public path on your web server. The dot files, images and map files are created in this directory and
  44 # served from there.
  45 CACHE_DIR  = "C:/DocumentRoot/cache/";
  46 CACHE_URL  = "http://MyWiki/cache/";
  47 
  48 # Absolute location of the dot (or neato) executable.
  49 DOT_EXE    = "C:/Programme/ATT/GraphViz/bin/neato.exe";
  50 
  51 # Colors of boxes and edges.
  52 BOX_COLOR  ="#E0F0FF";
  53 ROOT_COLOR = "#FFE0E0";
  54 STRONG_COLOR = "#E0FFE0";
  55 EDGE_COLOR ="#888888";
  56 
  57 # Categories are filtered in some way.
  58 CATEGORY_STRING = "^Kategorie"
  59 
  60 # Code starts here
  61 def execute(pagename, request):
  62     _ = request.getText;
  63     
  64     maxdepth = int(DEFAULT_DEPTH);
  65     if DEPTH_CONTROL and request.form.has_key('depth'):
  66       maxdepth = int(request.form['depth'].value);
  67     
  68     if int(maxdepth) > int(MAX_DEPTH):
  69       maxdepth = MAX_DEPTH;
  70       
  71     webapi.http_headers(request);
  72     wikiutil.send_title(request, _('Visual Map of %s') % (pagename), pagename=pagename);
  73 
  74     wikiname = wikiutil.quoteWikiname(pagename);
  75     dotfilename = '%s/%s.dot' % (CACHE_DIR, wikiname);
  76     pngfilename = '%s/%s.png' % (CACHE_DIR, wikiname);
  77     pngurl      = '%s/%s.png' % (CACHE_URL, wikiname);
  78     mapfilename = '%s/%s.cmap' % (CACHE_DIR, wikiname);
  79 
  80     dotfile = open(dotfilename,'w');
  81     
  82     dotfile.write('digraph G {\n');
  83     dotfile.write('  URL="%s";\n' % wikiname);
  84     dotfile.write('  ratio=compress;\n');
  85     dotfile.write('  overlap=false;\n');
  86     dotfile.write('  concentrate=true;\n');
  87     dotfile.write('  edge [color="%s"];\n' % EDGE_COLOR);
  88     dotfile.write('  node [URL="%s/\N", ' % ROOT_URL);
  89     dotfile.write('fontcolor=black, fontname=%s , fontsize=%s, style=filled, color="%s"]\n' % ("arial","8", BOX_COLOR));
  90     dotfile.write(LocalSiteMap(pagename, maxdepth).output(request));
  91     dotfile.write('}\n');
  92     dotfile.close();
  93     
  94     os.system('%s -Tpng -o%s %s' % (DOT_EXE, pngfilename, dotfilename));
  95     os.system('%s -Tcmap -o%s %s' % (DOT_EXE, mapfilename, dotfilename));
  96     
  97     print '<center><img class="sitemap" border=1 src="%s" usemap="#map1"></center>' % (pngurl);
  98     print '<map name="map1">';
  99     mapfile = open(mapfilename,'r');
 100     for row in mapfile.readlines():
 101         print row;
 102     mapfile.close();
 103       
 104     print '</map>';
 105     
 106     if DEPTH_CONTROL:
 107       print '<p align="center">';
 108       if maxdepth > 1:
 109           print '<a href="%s/%s?action=VisualSiteMap&depth=%s">Less</a>' % (ROOT_URL, pagename, maxdepth-1);
 110       else:
 111           print 'Less';
 112 
 113       print ' | ';
 114 
 115       if maxdepth < MAX_DEPTH:
 116           print '<a href="%s/%s?action=VisualSiteMap&depth=%s">More</a>' % (ROOT_URL, pagename, maxdepth+1);
 117       else:
 118           print 'More';
 119       print '</p>';
 120       
 121     print '<p align="center"><small>Search depth is %s. Nodes linked more than %s times are highlighted.</small></p>' % (maxdepth, STRONG_LINK_NR);
 122 
 123     wikiutil.send_footer(request, pagename);
 124     
 125     sys.exit(0);
 126 
 127 class LocalSiteMap:
 128     def __init__(self, name, maxdepth):
 129         self.name = name;
 130         self.result = [];
 131         self.maxdepth = maxdepth;
 132 
 133     def output(self, request):
 134         pagebuilder = GraphBuilder(request, self.maxdepth);
 135         root = pagebuilder.build_graph(self.name);
 136         # write nodes
 137         for node in pagebuilder.all_nodes:
 138             uname=unicode(node.name, config.charset).encode('UTF-8');
 139             self.append('  %s'% wikiutil.quoteWikiname(node.name));
 140             if node.depth > 0:
 141                 if node.linkedto >= STRONG_LINK_NR:
 142                     self.append('  [label="%s",color="%s"];\n' % (uname, STRONG_COLOR));
 143                 else:
 144                     self.append('  [label="%s"];\n' % (uname));
 145 
 146             else:
 147                 self.append('[label="%s",shape=box,style=filled,color="%s"];\n' % (uname, ROOT_COLOR));
 148         # write edges
 149         for edge in pagebuilder.all_edges:
 150             self.append('  %s->%s;\n' % (wikiutil.quoteWikiname(edge[0].name),wikiutil.quoteWikiname(edge[1].name)));
 151             
 152         return string.join(self.result, '');
 153 
 154     def append(self, text):
 155         self.result.append(text);
 156 
 157 
 158 class GraphBuilder:
 159     
 160     def __init__(self, request, maxdepth):
 161         self.request = request;
 162         self.maxdepth = maxdepth;
 163         self.all_nodes = [];
 164         self.all_edges = [];
 165         
 166     def is_ok(self, child):
 167         if not self.request.user.may.read(child):
 168             return 0;
 169         if Page(child).exists() and (not re.search(r'%s' % CATEGORY_STRING,child)):
 170             return 1;
 171         return 0;
 172 
 173     def build_graph(self, name):
 174         # Reuse generated trees
 175         nodesMap = {};
 176         root = Node(name);
 177         nodesMap[name] = root;
 178         root.visited = 1;
 179         self.all_nodes.append(root);
 180         self.recurse_build([root], 1, nodesMap);
 181         return root;
 182 
 183     def recurse_build(self, nodes, depth, nodesMap):
 184         # collect all nodes of the current search depth here for the next recursion step
 185         child_nodes = [];
 186         # iterate over the nodes
 187         for node in nodes:
 188             # print "<h2>Kids of %s</h2>" % node.name;
 189             for child in Page(node.name).getPageLinks(self.request):            
 190                 if self.is_ok(child):
 191                     # print "Child %s" % child;
 192                     # Create the node with the given name
 193                     if not nodesMap.has_key(child):
 194                         # create the new node and store it
 195                         newNode = Node(child);
 196                         newNode.depth = depth;
 197                         # print "is new";
 198                     else:
 199                         newNode = nodesMap[child];
 200                         # print "is old";
 201                     # print ". <br>";
 202                     # If the current depth doesn't exceed the maximum depth, add newNode to recursion step
 203                     if (int(depth) <= int(self.maxdepth)):
 204                         # The node is appended to the nodes list for the next recursion step.
 205                         nodesMap[child] = newNode;
 206                         self.all_nodes.append(newNode);
 207                         child_nodes.append(newNode);
 208                         node.append(newNode);
 209                         # Draw an edge.
 210                         self.all_edges.append((node, newNode));
 211                         newNode.linkedto += 1;
 212         # recurse, if the current recursion step yields children
 213         if len(child_nodes):
 214             self.recurse_build(child_nodes, depth+1, nodesMap);
 215 
 216 class Node:
 217     def __init__(self, name):
 218         self.name = name;
 219         self.children = [];
 220         self.visited = 0;
 221         self.linkedfrom = 0;
 222         self.linkedto = 0;
 223         self.depth = 0;
 224 
 225     def append(self, node):
 226         self.children.append(node);
 227         self.linkedfrom += 1;

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2011-04-14 07:28:03, 4.7 KB) [[attachment:CreateNewPage.py]]
  • [get | view] (2011-04-14 07:26:24, 4.2 KB) [[attachment:CreateNewPage1.6.py]]
  • [get | view] (2006-09-10 21:29:29, 40.4 KB) [[attachment:CreatePdfDocument2_0_3.py]]
  • [get | view] (2006-09-12 06:05:06, 40.5 KB) [[attachment:CreatePdfDocument2_0_4.py]]
  • [get | view] (2006-09-12 12:00:09, 40.6 KB) [[attachment:CreatePdfDocument2_0_5.py]]
  • [get | view] (2006-11-14 21:56:11, 43.5 KB) [[attachment:CreatePdfDocument2_0_6.py]]
  • [get | view] (2006-11-15 17:00:47, 43.8 KB) [[attachment:CreatePdfDocument2_0_7.py]]
  • [get | view] (2006-11-16 22:06:18, 43.8 KB) [[attachment:CreatePdfDocument2_0_8.py]]
  • [get | view] (2006-12-17 15:54:21, 43.6 KB) [[attachment:CreatePdfDocument2_0_9.py]]
  • [get | view] (2007-08-20 09:10:23, 67.2 KB) [[attachment:CreatePdfDocument2_1_0.py]]
  • [get | view] (2007-08-21 07:39:49, 67.1 KB) [[attachment:CreatePdfDocument2_1_1.py]]
  • [get | view] (2007-09-11 19:16:37, 67.3 KB) [[attachment:CreatePdfDocument2_1_2.py]]
  • [get | view] (2007-09-18 20:17:58, 68.1 KB) [[attachment:CreatePdfDocument2_1_3.py]]
  • [get | view] (2007-09-21 13:32:54, 71.1 KB) [[attachment:CreatePdfDocument2_1_4.py]]
  • [get | view] (2007-09-23 20:56:30, 73.4 KB) [[attachment:CreatePdfDocument2_1_5.py]]
  • [get | view] (2007-09-25 20:54:48, 74.5 KB) [[attachment:CreatePdfDocument2_2_0.py]]
  • [get | view] (2008-06-23 21:08:49, 77.0 KB) [[attachment:CreatePdfDocument2_3_0.py]]
  • [get | view] (2008-06-26 19:25:07, 81.0 KB) [[attachment:CreatePdfDocument2_3_1.py]]
  • [get | view] (2008-07-06 05:50:38, 83.1 KB) [[attachment:CreatePdfDocument2_3_2.py]]
  • [get | view] (2008-07-09 17:42:02, 83.3 KB) [[attachment:CreatePdfDocument2_3_3.py]]
  • [get | view] (2008-09-07 11:11:01, 83.5 KB) [[attachment:CreatePdfDocument2_3_4.py]]
  • [get | view] (2009-01-11 15:53:09, 84.3 KB) [[attachment:CreatePdfDocument2_3_5.py]]
  • [get | view] (2009-02-16 06:52:06, 84.2 KB) [[attachment:CreatePdfDocument2_3_6.py]]
  • [get | view] (2010-01-29 11:53:21, 82.8 KB) [[attachment:CreatePdfDocument2_4_0.py]]
  • [get | view] (2010-01-31 14:10:03, 84.6 KB) [[attachment:CreatePdfDocument2_4_1.py]]
  • [get | view] (2010-09-18 16:23:23, 85.6 KB) [[attachment:CreatePdfDocument2_4_2.py]]
  • [get | view] (2006-06-16 20:56:53, 4.9 KB) [[attachment:FlashManager.py-1.5.3-1]]
  • [get | view] (2003-12-07 18:15:53, 3.9 KB) [[attachment:HTML2MoinMoin.py]]
  • [get | view] (2005-10-16 08:24:35, 4.9 KB) [[attachment:HelpOn-1.3.5-4.py]]
  • [get | view] (2006-02-03 19:21:04, 4.9 KB) [[attachment:HelpOn-1.5.1-5.py]]
  • [get | view] (2006-07-04 10:45:22, 4.8 KB) [[attachment:HelpOn-1.5.4-6.py]]
  • [get | view] (2006-07-04 22:39:14, 4.8 KB) [[attachment:HelpOn-1.6.0-7.py]]
  • [get | view] (2006-07-06 13:50:17, 4.0 KB) [[attachment:HelpOn-1.6.0-8.py]]
  • [get | view] (2008-01-10 17:43:24, 4.8 KB) [[attachment:HelpOn-1.6.0-9.py]]
  • [get | view] (2008-08-19 14:44:54, 5.0 KB) [[attachment:HelpOn-1.7.1-10.py]]
  • [get | view] (2005-02-20 18:28:34, 10.8 KB) [[attachment:IRSS.py]]
  • [get | view] (2005-03-09 22:46:23, 2.9 KB) [[attachment:ImportHtml-1.2.py]]
  • [get | view] (2003-12-07 18:15:53, 2.8 KB) [[attachment:ImportHtml.py]]
  • [get | view] (2003-12-07 18:15:53, 1.8 KB) [[attachment:IrcChat.py]]
  • [get | view] (2008-06-09 11:27:20, 4.4 KB) [[attachment:MoinCrypt.py]]
  • [get | view] (2010-11-29 12:08:27, 7.5 KB) [[attachment:PageActions.py]]
  • [get | view] (2006-08-07 15:12:19, 0.5 KB) [[attachment:PermanentLink.py]]
  • [get | view] (2003-12-07 18:15:53, 6.3 KB) [[attachment:PhoneDial.py]]
  • [get | view] (2005-04-17 14:21:47, 3.6 KB) [[attachment:RecommendPage-1.3.4-1.py]]
  • [get | view] (2005-04-19 18:21:52, 5.5 KB) [[attachment:RecommendPage-1.3.4-2.py]]
  • [get | view] (2005-05-02 19:53:09, 5.6 KB) [[attachment:RecommendPage-1.3.4-3.py]]
  • [get | view] (2005-09-03 07:33:35, 6.3 KB) [[attachment:RecommendPage-1.3.4-4.py]]
  • [get | view] (2005-09-05 17:44:03, 6.9 KB) [[attachment:RecommendPage-1.3.5-5.py]]
  • [get | view] (2005-09-07 16:42:26, 7.5 KB) [[attachment:RecommendPage-1.3.5-6.py]]
  • [get | view] (2005-09-08 16:06:28, 7.7 KB) [[attachment:RecommendPage-1.3.5-7.py]]
  • [get | view] (2005-11-01 11:31:51, 9.0 KB) [[attachment:RecommendPage-1.3.5-8.py]]
  • [get | view] (2006-02-03 19:40:51, 8.3 KB) [[attachment:RecommendPage-1.5.1-9.py]]
  • [get | view] (2008-01-11 09:14:35, 6.8 KB) [[attachment:RecommendPage-1.6.0-10.py]]
  • [get | view] (2008-08-19 14:44:59, 6.9 KB) [[attachment:RecommendPage-1.7.1-11.py]]
  • [get | view] (2008-06-09 11:27:40, 1.7 KB) [[attachment:ShowActions.py]]
  • [get | view] (2008-06-09 10:34:02, 5.3 KB) [[attachment:ShowDecrypted.py]]
  • [get | view] (2005-03-30 21:17:28, 7.7 KB) [[attachment:Slideshow.py]]
  • [get | view] (2004-02-02 20:48:31, 2.0 KB) [[attachment:SubscribeUser.py]]
  • [get | view] (2007-01-26 17:08:30, 2.2 KB) [[attachment:Subscribers-1.6.0.py]]
  • [get | view] (2003-12-07 18:15:53, 1.8 KB) [[attachment:Subscribers.py]]
  • [get | view] (2006-03-18 23:16:51, 0.8 KB) [[attachment:UserPreferences.py]]
  • [get | view] (2004-01-05 09:56:25, 8.1 KB) [[attachment:VisualSiteMap.py]]
  • [get | view] (2015-08-30 21:04:23, 11.1 KB) [[attachment:VisualSiteMap_1.10.py]]
  • [get | view] (2004-10-08 10:59:16, 9.3 KB) [[attachment:VisualSiteMap_1.2.py]]
  • [get | view] (2005-03-16 01:30:09, 9.8 KB) [[attachment:VisualSiteMap_1.3.py]]
  • [get | view] (2014-08-19 01:34:10, 10.8 KB) [[attachment:VisualSiteMap_1.9.py]]
  • [get | view] (2007-08-18 18:52:55, 1.0 KB) [[attachment:backlink.py]]
  • [get | view] (2007-03-15 05:53:49, 23.5 KB) [[attachment:findandreplace0.1Beta.py]]
  • [get | view] (2005-03-27 20:32:10, 3.6 KB) [[attachment:gallery2image-1.3.3-1.py]]
  • [get | view] (2005-08-03 20:14:56, 4.0 KB) [[attachment:gallery2image-1.3.3-2.py]]
  • [get | view] (2005-11-13 18:10:26, 20.7 KB) [[attachment:gallery2image-1.3.5-10.py]]
  • [get | view] (2005-11-25 22:03:50, 20.8 KB) [[attachment:gallery2image-1.3.5-11.py]]
  • [get | view] (2005-08-08 17:23:43, 8.4 KB) [[attachment:gallery2image-1.3.5-4.py]]
  • [get | view] (2005-08-13 15:15:45, 13.7 KB) [[attachment:gallery2image-1.3.5-5.py]]
  • [get | view] (2005-08-31 22:05:22, 15.5 KB) [[attachment:gallery2image-1.3.5-6.py]]
  • [get | view] (2005-10-29 20:23:50, 15.9 KB) [[attachment:gallery2image-1.3.5-8.py]]
  • [get | view] (2005-11-01 11:31:24, 17.6 KB) [[attachment:gallery2image-1.3.5-9.py]]
  • [get | view] (2006-01-27 20:52:32, 20.9 KB) [[attachment:gallery2image-1.5.1-12.py]]
  • [get | view] (2006-08-06 09:01:01, 22.1 KB) [[attachment:gallery2image-1.5.4-13.py]]
  • [get | view] (2006-08-11 18:21:40, 22.2 KB) [[attachment:gallery2image-1.5.4-14.py]]
  • [get | view] (2006-11-16 20:23:27, 22.6 KB) [[attachment:gallery2image-1.5.6-16.py]]
  • [get | view] (2006-08-11 18:30:22, 22.2 KB) [[attachment:gallery2image-1.6.0-15.py]]
  • [get | view] (2008-02-06 10:13:45, 22.3 KB) [[attachment:gallery2image-1.6.0-16.py]]
  • [get | view] (2008-05-20 15:51:09, 22.4 KB) [[attachment:gallery2image-1.6.3-17.py]]
  • [get | view] (2006-09-06 06:19:48, 1.3 KB) [[attachment:getmmap.py]]
  • [get | view] (2004-07-18 09:48:00, 1.5 KB) [[attachment:localnames.py]]
  • [get | view] (2005-03-25 15:02:31, 2.6 KB) [[attachment:newpageonly.py]]
  • [get | view] (2005-03-30 09:02:00, 3.5 KB) [[attachment:newpageonly_20050330.py]]
  • [get | view] (2006-06-06 19:12:27, 9.7 KB) [[attachment:pdf.py]]
  • [get | view] (2006-08-30 10:51:51, 36.0 KB) [[attachment:pdf2_0_0.py]]
  • [get | view] (2006-08-30 13:57:36, 36.5 KB) [[attachment:pdf2_0_1.py]]
  • [get | view] (2006-02-04 04:25:29, 1.0 KB) [[attachment:sisterindex.py]]
  • [get | view] (2004-10-28 07:33:10, 0.7 KB) [[attachment:xml.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.