iwla

iwla Git Source Tree

Root/display.py

1# -*- coding: utf-8 -*-
2#
3# Copyright Grégory Soutadé 2015
4
5# This file is part of iwla
6
7# iwla is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# iwla is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with iwla. If not, see <http://www.gnu.org/licenses/>.
19#
20
21import os
22import codecs
23import time
24import logging
25
26#
27# Create output HTML files
28#
29
30# Just for detection
31def _(name): pass
32_('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July')
33_('August'), _('September'), _('October'), _('November'), _('December')
34del _
35
36class DisplayHTMLRaw(object):
37
38 def __init__(self, iwla, html=u''):
39 self.iwla = iwla
40 self.html = html
41
42 def setRawHTML(self, html):
43 self.html = html
44
45 def _buildHTML(self):
46 pass
47
48 def _build(self, f, html):
49 if html: f.write(html)
50
51 def build(self, f):
52 self._buildHTML()
53 self._build(f, self.html)
54
55class DisplayHTMLBlock(DisplayHTMLRaw):
56
57 def __init__(self, iwla, title=''):
58 super(DisplayHTMLBlock, self).__init__(iwla, html='')
59 self.title = title
60 self.cssclass = u'iwla_block'
61 self.title_cssclass = u'iwla_block_title'
62 self.value_cssclass = u'iwla_block_value'
63
64 def getTitle(self):
65 return self.title
66
67 def setTitle(self, value):
68 self.title = unicode(value)
69
70 def setCSSClass(self, cssclass):
71 self.cssclass = unicode(cssclass)
72
73 def setTitleCSSClass(self, cssclass):
74 self.title_cssclass = unicode(cssclass)
75
76 def setValueCSSClass(self, cssclass):
77 self.value_cssclass = unicode(cssclass)
78
79 def _buildHTML(self):
80 html = u'<div class="%s">' % (self.cssclass)
81 if self.title:
82 html += u'<div class="%s">%s</div>' % (self.title_cssclass, self.title)
83 html += u'<div class="%s">%s</div>' % (self.value_cssclass, self.html)
84 html += u'</div>'
85
86 self.html = html
87
88class DisplayHTMLBlockTable(DisplayHTMLBlock):
89
90 def __init__(self, iwla, title, cols):
91 super(DisplayHTMLBlockTable, self).__init__(iwla=iwla, title=title)
92 self.cols = listToStr(cols)
93 self.rows = []
94 self.cols_cssclasses = [u''] * len(cols)
95 self.rows_cssclasses = []
96 self.table_css = u'iwla_table'
97
98 def appendRow(self, row):
99 self.rows.append(listToStr(row))
100 self.rows_cssclasses.append([u''] * len(row))
101
102 def getNbRows(self):
103 return len(self.rows)
104
105 def getNbCols(self):
106 return len(self.cols)
107
108 def getCellValue(self, row, col):
109 if row < 0 or col < 0 or\
110 row >= len(self.rows) or col >= len(self.cols):
111 raise ValueError('Invalid indices %d,%d' % (row, col))
112
113 return self.rows[row][col]
114
115 def setCellValue(self, row, col, value):
116 if row < 0 or col < 0 or\
117 row >= len(self.rows) or col >= len(self.cols):
118 raise ValueError('Invalid indices %d,%d' % (row, col))
119
120 self.rows[row][col] = unicode(value)
121
122 def setCellCSSClass(self, row, col, value):
123 if row < 0 or col < 0 or\
124 row >= len(self.rows) or col >= len(self.cols):
125 raise ValueError('Invalid indices %d,%d' % (row, col))
126
127 self.rows_cssclasses[row][col] = unicode(value)
128
129 def getCellCSSClass(self, row, col):
130 if row < 0 or col < 0 or\
131 row >= len(self.rows) or col >= len(self.cols):
132 raise ValueError('Invalid indices %d,%d' % (row, col))
133
134 return self.rows_cssclasses[row][col]
135
136 def getColCSSClass(self, col):
137 if col < 0 or col >= len(self.cols):
138 raise ValueError('Invalid indice %d' % (col))
139
140 return self.cols_cssclasses[col]
141
142 def setRowCSSClass(self, row, value):
143 if row < 0 or row >= len(self.rows):
144 raise ValueError('Invalid indice %d' % (row))
145
146 self.rows_cssclasses[row] = [unicode(value)] * len(self.rows_cssclasses[row])
147
148 def setColCSSClass(self, col, value):
149 if col < 0 or col >= len(self.cols):
150 raise ValueError('Invalid indice %d' % (col))
151
152 self.cols_cssclasses[col] = unicode(value)
153
154 def setColsCSSClass(self, values):
155 if len(values) != len(self.cols):
156 raise ValueError('Invalid values size')
157
158 self.cols_cssclasses = listToStr(values)
159
160 def _buildHTML(self):
161 style = u''
162 if self.table_css: style = u' class="%s"' % (self.table_css)
163 html = u'<table%s>' % (style)
164 if self.cols:
165 html += u'<tr>'
166 for i in range (0, len(self.cols)):
167 title = self.cols[i]
168 style = self.getColCSSClass(i)
169 if style: style = u' class="%s"' % (style)
170 html += u'<th%s>%s</th>' % (style, title)
171 html += u'</tr>'
172 for i in range(0, len(self.rows)):
173 row = self.rows[i]
174 html += u'<tr>'
175 for j in range(0, len(row)):
176 v = row[j]
177 style = self.getCellCSSClass(i, j)
178 if style: style = u' class="%s"' % (style)
179 html += u'<td%s>%s</td>' % (style, v)
180 html += u'</tr>'
181 html += u'</table>'
182
183 self.html += html
184
185 super(DisplayHTMLBlockTable, self)._buildHTML()
186
187class DisplayHTMLBlockTableWithGraph(DisplayHTMLBlockTable):
188
189 def __init__(self, iwla, title, cols, short_titles=None, nb_valid_rows=0, graph_cols=None):
190 super(DisplayHTMLBlockTableWithGraph, self).__init__(iwla=iwla, title=title, cols=cols)
191 self.short_titles = short_titles or []
192 self.short_titles = listToStr(self.short_titles)
193 self.nb_valid_rows = nb_valid_rows
194 self.icon_path = self.iwla.getConfValue('icon_path', '/')
195 self.raw_rows = []
196 self.maxes = [0] * len(cols)
197 self.table_graph_css = u'iwla_graph_table'
198 self.td_img_css = u'iwla_td_img'
199 self.graph_cols = graph_cols or []
200
201 def appendRow(self, row):
202 self.raw_rows.append(row)
203 super(DisplayHTMLBlockTableWithGraph, self).appendRow(row)
204
205 def appendShortTitle(self, short_title):
206 self.short_titles.append(unicode(short_title))
207
208 def setShortTitle(self, short_titles):
209 self.short_titles = listToStr(short_titles)
210
211 def setNbValidRows(self, nb_valid_rows):
212 self.nb_valid_rows = nb_valid_rows
213
214 def _computeMax(self):
215 for i in range(0, self.nb_valid_rows):
216 row = self.raw_rows[i]
217 for j in range(1, len(row)):
218 if row[j] > self.maxes[j]:
219 self.maxes[j] = row[j]
220
221 def _getIconFromStyle(self, style):
222 if style.startswith(u'iwla_page'): icon = u'vp.png'
223 elif style.startswith(u'iwla_hit'): icon = u'vh.png'
224 elif style.startswith(u'iwla_bandwidth'): icon = u'vk.png'
225 elif style.startswith(u'iwla_visitor'): icon = u'vu.png'
226 elif style.startswith(u'iwla_visit'): icon = u'vv.png'
227 else: return ''
228
229 return u'/%s/%s' % (self.icon_path, icon)
230
231 def _buildHTML(self):
232 self._computeMax()
233
234 style = u''
235 if self.table_graph_css: style = u' class="%s"' % (self.table_graph_css)
236 html = u'<table%s>' % (style)
237 html += u'<tr>'
238 for i in range(0, self.nb_valid_rows):
239 row = self.rows[i]
240 css = u''
241 if self.td_img_css: css=u' class="%s"' % (self.td_img_css)
242 html += u'<td%s>' % (css)
243 for j in self.graph_cols:
244 style = self.getColCSSClass(j)
245 icon = self._getIconFromStyle(style)
246 if not icon: continue
247 if style: style = u' class="%s"' % (style)
248 alt = u'%s: %s' % (row[j], self.cols[j])
249 if self.maxes[j]:
250 height = int((self.raw_rows[i][j] * 100) / self.maxes[j]) or 1
251 else:
252 height = 1
253 html += u'<img%s src="%s" height="%d" width="6" alt="%s" title="%s" />' % (style, icon, height, alt, alt)
254 html += u'</td>'
255 html += u'</tr>'
256 html += u'<tr>'
257 for i in range(0, len(self.short_titles)):
258 style = self.getCellCSSClass(i, 0)
259 if style: style = u' class="%s"' % (style)
260 html += u'<td%s>%s</td>' % (style, self.short_titles[i])
261 html += u'</tr>'
262 html += u'</table>'
263
264 self.html += html
265
266 super(DisplayHTMLBlockTableWithGraph, self)._buildHTML()
267
268class DisplayHTMLPage(object):
269
270 def __init__(self, iwla, title, filename, css_path):
271 self.iwla = iwla
272 self.title = unicode(title)
273 self.filename = filename
274 self.blocks = []
275 self.css_path = listToStr(css_path)
276 self.logger = logging.getLogger(self.__class__.__name__)
277
278 def getFilename(self):
279 return self.filename;
280
281 def getBlock(self, title):
282 for b in self.blocks:
283 if title == b.getTitle():
284 return b
285 return None
286
287 def appendBlock(self, block):
288 self.blocks.append(block)
289
290 def build(self, root):
291 filename = os.path.join(root, self.filename)
292
293 base = os.path.dirname(filename)
294 if not os.path.exists(base):
295 os.makedirs(base)
296
297 self.logger.debug('Write %s' % (filename))
298
299 f = codecs.open(filename, 'w', 'utf-8')
300 f.write(u'<!DOCTYPE html>')
301 f.write(u'<html>')
302 f.write(u'<head>')
303 f.write(u'<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />')
304 for css in self.css_path:
305 f.write(u'<link rel="stylesheet" href="/%s"/>' % (css))
306 if self.title:
307 f.write(u'<title>%s</title>' % (self.title))
308 f.write(u'</head>')
309 for block in self.blocks:
310 block.build(f)
311 f.write(u'<center>Generated by <a href="%s">IWLA %s</a></center>' %
312 ("http://indefero.soutade.fr/p/iwla", self.iwla.getVersion()))
313 f.write(u'</body></html>')
314 f.close()
315
316class DisplayHTMLBuild(object):
317
318 def __init__(self, iwla):
319 self.pages = []
320 self.iwla = iwla
321
322 def createPage(self, *args):
323 return DisplayHTMLPage(self.iwla, *args)
324
325 def createBlock(self, _class, *args):
326 return _class(self.iwla, *args)
327
328 def getPage(self, filename):
329 for page in self.pages:
330 if page.getFilename() == filename:
331 return page
332 return None
333
334 def addPage(self, page):
335 self.pages.append(page)
336
337 def build(self, root):
338 display_root = self.iwla.getConfValue('DISPLAY_ROOT', '')
339 if not os.path.exists(display_root):
340 os.makedirs(display_root)
341 for res_path in self.iwla.getResourcesPath():
342 target = os.path.abspath(res_path)
343 link_name = os.path.join(display_root, res_path)
344 if not os.path.exists(link_name):
345 os.symlink(target, link_name)
346
347 for page in self.pages:
348 page.build(root)
349
350#
351# Global functions
352#
353
354def bytesToStr(bytes):
355 suffixes = [u'', u' kB', u' MB', u' GB', u' TB']
356
357 for i in range(0, len(suffixes)):
358 if bytes < 1024: break
359 bytes /= 1024.0
360
361 if i:
362 return u'%.02f%s' % (bytes, suffixes[i])
363 else:
364 return u'%d%s' % (bytes, suffixes[i])
365
366def _toStr(v):
367 if type(v) != unicode: return unicode(v)
368 else: return v
369
370def listToStr(l): return map(lambda(v) : _toStr(v), l)
371
372def generateHTMLLink(url, name=None, max_length=100, prefix=u'http'):
373 url = unicode(url)
374 if not name: name = unicode(url)
375 if not url.startswith(prefix): url = u'%s://%s' % (prefix, url)
376 return u'<a href="%s">%s</a>' % (url, name[:max_length])
377
378def createCurTitle(iwla, title):
379 title = iwla._(title)
380 month_name = time.strftime(u'%B', iwla.getCurTime())
381 year = time.strftime(u'%Y', iwla.getCurTime())
382 title += u' - %s %s' % (iwla._(month_name), year)
383 domain_name = iwla.getConfValue('domain_name', '')
384 if domain_name:
385 title += u' - %s' % (domain_name)
386 return title
387

Archive Download this file

Branches

Tags