File: Synopsis/Formatters/HTML/Views/FileIndex.py
  1#
  2# Copyright (C) 2000 Stephen Davies
  3# Copyright (C) 2000 Stefan Seefeld
  4# All rights reserved.
  5# Licensed to the public under the terms of the GNU LGPL (>= 2),
  6# see the file COPYING for details.
  7#
  8
  9from Synopsis.Processor import Parameter
 10from Synopsis import ASG
 11from Synopsis.QualifiedName import *
 12from Synopsis.Formatters.HTML.View import View
 13from Synopsis.Formatters.HTML.Tags import *
 14import os
 15
 16class FileIndex(View):
 17    """A view that creates an index of files, and an index for each file.
 18    First the index of files is created, intended for the top-left frame.
 19    Second a view is created for each file, listing the major declarations for
 20    that file, eg: classes, global functions, namespaces, etc."""
 21
 22    def register(self, frame):
 23
 24       super(FileIndex, self).register(frame)
 25       self.__filename = ''
 26       self.__title = ''
 27       self.link_source = self.processor.has_view('Source') and self.processor.sxr_prefix
 28       self.link_details = self.processor.has_view('FileDetails')
 29
 30    def filename(self):
 31        """since FileTree generates a whole file hierarchy, this method returns the current filename,
 32        which may change over the lifetime of this object"""
 33
 34        return self.__filename
 35
 36    def title(self):
 37        """since FileTree generates a while file hierarchy, this method returns the current title,
 38        which may change over the lifetime of this object"""
 39
 40        return self.__title
 41
 42    def register_filenames(self):
 43        """Registers a view for each file indexed."""
 44
 45        for filename, file in self.processor.ir.files.items():
 46            if file.annotations['primary']:
 47                filename = self.directory_layout.file_index(filename)
 48                self.processor.register_filename(filename, self, file)
 49
 50    def process(self):
 51        """Creates a view for each known file."""
 52
 53        for filename, file in self.processor.ir.files.items():
 54            if file.annotations['primary']:
 55                self.process_file(filename, file)
 56
 57    def process_file(self, filename, file):
 58        """Creates a view for the given file. The view is just an index,
 59        containing a list of declarations."""
 60
 61        # set up filename and title for the current view
 62        self.__filename = self.directory_layout.file_index(filename)
 63        # (get rid of ../'s in the filename)
 64        name = filename.split(os.sep)
 65        while len(name) and name[0] == '..': del name[0]
 66        self.__title = os.sep.join(name)
 67
 68        self.start_file()
 69        self.write(element('b', os.sep.join(name))+'\n')
 70        if self.link_source:
 71            link = rel(self.filename(),
 72                      self.directory_layout.file_source(filename))
 73            self.write(div('', href(link, 'source code', target='content')) + '\n')
 74        if self.link_details:
 75            link = rel(self.filename(),
 76                       self.directory_layout.file_details(filename))
 77            self.write(div('', href(link, 'details', target='content')) + '\n')
 78
 79        self.write(div('heading', 'Declarations') + '\n')
 80        # Sort items (by name)
 81        items = [(d.name, d) for d in file.declarations]
 82        items.sort()
 83        if file.annotations.get('language') == 'Python':
 84            scope = QualifiedPythonName()
 85        else:
 86            scope = QualifiedCxxName()
 87        last = scope
 88        for name, decl in items:
 89            entry = self.processor.toc[name]
 90            if not entry: continue
 91            # Print link to declaration's view
 92            link = rel(self.filename(), entry.link)
 93            label = isinstance(decl, ASG.Function) and decl.real_name or decl.name
 94            i = 0
 95            while i < len(label) - 1 and i < len(scope) and label[i] == scope[i]:
 96                i += 1
 97            self.write('</div>' * (len(scope) - i))
 98            scope = scope[:i]
 99            while i < len(label) - 1:
100                scope = scope + (label[i],)
101                if len(last) >= len(scope) and last[:len(scope)] == scope: div_bit = ''
102                else: div_bit = label[i]+'<br/>\n'
103                self.write('%s<div class="fileview-scope">'%div_bit)
104                i += 1
105
106            # Now print the actual item
107            label = replace_spaces(escape(str(scope.prune(label))))
108            title = '(%s)'%decl.type
109            self.write(div('href',href(link, label, target='content', title=title)))
110            # Store this name in case, f.ex, it's a class and the next item is
111            # in that class scope
112            last = name
113        self.write('</div>\n' * len(scope))
114        self.end_file()
115