File: Synopsis/Formatters/HTML/Views/FileDetails.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.Formatters.HTML.View import View
 12from Synopsis.Formatters.HTML.Tags import *
 13from Source import *
 14import os
 15
 16class FileDetails(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(FileDetails, self).register(frame)
 25      self.__filename = ''
 26      self.__title = ''
 27      self.link_source = self.processor.has_view('Source') and self.processor.sxr_prefix
 28
 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_details(filename)
 48            self.processor.register_filename(filename, self, file)
 49
 50   def process(self):
 51      """Creates a view for each known source 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_details(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)+' Details'
 67
 68      self.start_file()
 69      self.write_navigation_bar()
 70      self.write(element('h1', os.sep.join(name)))
 71      if self.link_source:
 72         link = rel(self.filename(),
 73                    self.directory_layout.file_source(filename))
 74         self.write(div('', href(link, 'source code', target='content')) + '\n')
 75
 76      # Print list of includes
 77      try:
 78         # Only show files from the project
 79         includes = [i for i in file.includes if i.target.annotations['primary']]
 80         self.write('<h2 class="heading">Includes from this file:</h2>')
 81         if not includes:
 82            self.write('<p>No includes.</p>\n')
 83         else:
 84            self.write('<ul>\n')
 85            for include in includes:
 86               target_filename = include.target.name
 87               if include.is_next: idesc = 'include_next '
 88               else: idesc = 'include '
 89               if include.is_macro: idesc = idesc + 'from macro '
 90               link = rel(self.filename(), self.directory_layout.file_details(target_filename))
 91               self.write('<li>' + idesc + href(link, target_filename)+'</li>\n')
 92            self.write('</ul>\n')
 93      except:
 94         pass
 95
 96      self.write('<h2 class="heading">Declarations in this file:</h2>\n')
 97      # Sort items (by name)
 98      items = [(d.type, d.name, d) for d in file.declarations
 99               # We don't want to list (function, template) parameters, and neither 'this'.
100               if type(d) is not ASG.Parameter and d.type not in ('this', 'parameter', 'local variable')]
101      # ignore ASG.Builtin
102      items = [i for i in items if not isinstance(i[2], ASG.Builtin)]
103      items.sort()
104      curr_scope = None
105      curr_type = None
106      for decl_type, name, decl in items:
107         # Check scope and type to see if they've changed since the last
108         # declaration, thereby forming sections of scope and type
109         decl_scope = name[:-1]
110         if decl_scope != curr_scope or decl_type != curr_type:
111            if curr_scope is not None:
112               self.write('\n</div>\n')
113            curr_scope = decl_scope
114            curr_type = decl_type
115            if len(curr_type) and curr_type[-1] == 's': plural = 'es'
116            else: plural = 's'
117            if len(curr_scope):
118               self.write('<div><h3>%s%s in %s</h3>\n'%(
119                  curr_type.capitalize(), plural, escape(str(curr_scope))))
120            else:
121               self.write('<div><h3>%s%s</h3>\n'%(curr_type.capitalize(),plural))
122
123         # Format this declaration
124         entry = self.processor.toc[name]
125         label = escape(str(curr_scope.prune(name)))
126         label = replace_spaces(label)
127         if entry:
128            link = rel(self.filename(), entry.link)
129            item = href(link, label)
130         else:
131            item = label
132         doc = div('doc', self.processor.documentation.summary(decl, self))
133         self.write(div('item', item + '\n' + doc) + '\n')
134
135      # Close open div
136      if curr_scope is not None:
137         self.write('</div>\n')
138      self.end_file()
139