OLD | NEW |
(Empty) | |
| 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
| 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
| 3 # |
| 4 # This file is part of logilab-common. |
| 5 # |
| 6 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
| 7 # the terms of the GNU Lesser General Public License as published by the Free |
| 8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
| 9 # later version. |
| 10 # |
| 11 # logilab-common is distributed in the hope that it will be useful, but WITHOUT |
| 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
| 14 # details. |
| 15 # |
| 16 # You should have received a copy of the GNU Lesser General Public License along |
| 17 # with logilab-common. If not, see <http://www.gnu.org/licenses/>. |
| 18 """Micro reports objects. |
| 19 |
| 20 A micro report is a tree of layout and content objects. |
| 21 """ |
| 22 __docformat__ = "restructuredtext en" |
| 23 |
| 24 from logilab.common.tree import VNode |
| 25 |
| 26 class BaseComponent(VNode): |
| 27 """base report component |
| 28 |
| 29 attributes |
| 30 * id : the component's optional id |
| 31 * klass : the component's optional klass |
| 32 """ |
| 33 def __init__(self, id=None, klass=None): |
| 34 VNode.__init__(self, id) |
| 35 self.klass = klass |
| 36 |
| 37 class BaseLayout(BaseComponent): |
| 38 """base container node |
| 39 |
| 40 attributes |
| 41 * BaseComponent attributes |
| 42 * children : components in this table (i.e. the table's cells) |
| 43 """ |
| 44 def __init__(self, children=(), **kwargs): |
| 45 super(BaseLayout, self).__init__(**kwargs) |
| 46 for child in children: |
| 47 if isinstance(child, BaseComponent): |
| 48 self.append(child) |
| 49 else: |
| 50 self.add_text(child) |
| 51 |
| 52 def append(self, child): |
| 53 """overridden to detect problems easily""" |
| 54 assert child not in self.parents() |
| 55 VNode.append(self, child) |
| 56 |
| 57 def parents(self): |
| 58 """return the ancestor nodes""" |
| 59 assert self.parent is not self |
| 60 if self.parent is None: |
| 61 return [] |
| 62 return [self.parent] + self.parent.parents() |
| 63 |
| 64 def add_text(self, text): |
| 65 """shortcut to add text data""" |
| 66 self.children.append(Text(text)) |
| 67 |
| 68 |
| 69 # non container nodes ######################################################### |
| 70 |
| 71 class Text(BaseComponent): |
| 72 """a text portion |
| 73 |
| 74 attributes : |
| 75 * BaseComponent attributes |
| 76 * data : the text value as an encoded or unicode string |
| 77 """ |
| 78 def __init__(self, data, escaped=True, **kwargs): |
| 79 super(Text, self).__init__(**kwargs) |
| 80 #if isinstance(data, unicode): |
| 81 # data = data.encode('ascii') |
| 82 assert isinstance(data, (str, unicode)), data.__class__ |
| 83 self.escaped = escaped |
| 84 self.data = data |
| 85 |
| 86 class VerbatimText(Text): |
| 87 """a verbatim text, display the raw data |
| 88 |
| 89 attributes : |
| 90 * BaseComponent attributes |
| 91 * data : the text value as an encoded or unicode string |
| 92 """ |
| 93 |
| 94 class Link(BaseComponent): |
| 95 """a labelled link |
| 96 |
| 97 attributes : |
| 98 * BaseComponent attributes |
| 99 * url : the link's target (REQUIRED) |
| 100 * label : the link's label as a string (use the url by default) |
| 101 """ |
| 102 def __init__(self, url, label=None, **kwargs): |
| 103 super(Link, self).__init__(**kwargs) |
| 104 assert url |
| 105 self.url = url |
| 106 self.label = label or url |
| 107 |
| 108 |
| 109 class Image(BaseComponent): |
| 110 """an embedded or a single image |
| 111 |
| 112 attributes : |
| 113 * BaseComponent attributes |
| 114 * filename : the image's filename (REQUIRED) |
| 115 * stream : the stream object containing the image data (REQUIRED) |
| 116 * title : the image's optional title |
| 117 """ |
| 118 def __init__(self, filename, stream, title=None, **kwargs): |
| 119 super(Image, self).__init__(**kwargs) |
| 120 assert filename |
| 121 assert stream |
| 122 self.filename = filename |
| 123 self.stream = stream |
| 124 self.title = title |
| 125 |
| 126 |
| 127 # container nodes ############################################################# |
| 128 |
| 129 class Section(BaseLayout): |
| 130 """a section |
| 131 |
| 132 attributes : |
| 133 * BaseLayout attributes |
| 134 |
| 135 a title may also be given to the constructor, it'll be added |
| 136 as a first element |
| 137 a description may also be given to the constructor, it'll be added |
| 138 as a first paragraph |
| 139 """ |
| 140 def __init__(self, title=None, description=None, **kwargs): |
| 141 super(Section, self).__init__(**kwargs) |
| 142 if description: |
| 143 self.insert(0, Paragraph([Text(description)])) |
| 144 if title: |
| 145 self.insert(0, Title(children=(title,))) |
| 146 |
| 147 class Title(BaseLayout): |
| 148 """a title |
| 149 |
| 150 attributes : |
| 151 * BaseLayout attributes |
| 152 |
| 153 A title must not contains a section nor a paragraph! |
| 154 """ |
| 155 |
| 156 class Span(BaseLayout): |
| 157 """a title |
| 158 |
| 159 attributes : |
| 160 * BaseLayout attributes |
| 161 |
| 162 A span should only contains Text and Link nodes (in-line elements) |
| 163 """ |
| 164 |
| 165 class Paragraph(BaseLayout): |
| 166 """a simple text paragraph |
| 167 |
| 168 attributes : |
| 169 * BaseLayout attributes |
| 170 |
| 171 A paragraph must not contains a section ! |
| 172 """ |
| 173 |
| 174 class Table(BaseLayout): |
| 175 """some tabular data |
| 176 |
| 177 attributes : |
| 178 * BaseLayout attributes |
| 179 * cols : the number of columns of the table (REQUIRED) |
| 180 * rheaders : the first row's elements are table's header |
| 181 * cheaders : the first col's elements are table's header |
| 182 * title : the table's optional title |
| 183 """ |
| 184 def __init__(self, cols, title=None, |
| 185 rheaders=0, cheaders=0, rrheaders=0, rcheaders=0, |
| 186 **kwargs): |
| 187 super(Table, self).__init__(**kwargs) |
| 188 assert isinstance(cols, int) |
| 189 self.cols = cols |
| 190 self.title = title |
| 191 self.rheaders = rheaders |
| 192 self.cheaders = cheaders |
| 193 self.rrheaders = rrheaders |
| 194 self.rcheaders = rcheaders |
| 195 |
| 196 class List(BaseLayout): |
| 197 """some list data |
| 198 |
| 199 attributes : |
| 200 * BaseLayout attributes |
| 201 """ |
OLD | NEW |